mirror of
https://github.com/espressif/openthread.git
synced 2026-10-29 02:33:56 +00:00
[k32w] use a custom Persistent Data Manager (#5496)
This commit add support for a custom PDM (Persistent Data Manager) which is also used inside Project CHIP. Signed-off-by: Doru Gucea <[email protected]>
This commit is contained in:
+13
-13
@@ -81,19 +81,19 @@ CONFIG_FILE = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-jn5189
|
||||
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/k32w/jn5189/
|
||||
SIGN_IMAGE_PATH = $(AbsTopSourceDir)/third_party/nxp/JN5189DK6/tools/imagetool/
|
||||
|
||||
COMMONCFLAGS := \
|
||||
-fdata-sections \
|
||||
-ffunction-sections \
|
||||
-Os \
|
||||
-g \
|
||||
-DCPU_JN518X \
|
||||
-DCPU_JN518X_REV=2 \
|
||||
-DJENNIC_CHIP_FAMILY_JN518x \
|
||||
-DJENNIC_CHIP_FAMILY_NAME=_JN518x \
|
||||
-DSDK_DEBUGCONSOLE=0 \
|
||||
-D$(CONFIG_FILE) \
|
||||
-DUSE_RTOS=0 \
|
||||
-I$(CONFIG_FILE_PATH) \
|
||||
COMMONCFLAGS :=\
|
||||
-fdata-sections \
|
||||
-ffunction-sections \
|
||||
-Os \
|
||||
-g \
|
||||
-DCPU_JN518X \
|
||||
-DCPU_JN518X_REV=2 \
|
||||
-DJENNIC_CHIP_FAMILY_JN518x \
|
||||
-DJENNIC_CHIP_FAMILY_NAME=_JN518x \
|
||||
-DSDK_DEBUGCONSOLE=0 \
|
||||
-D$(CONFIG_FILE) \
|
||||
-imacros "$(AbsTopSourceDir)/examples/platforms/k32w/jn5189/jn5189-sdk-config.h" \
|
||||
-I$(CONFIG_FILE_PATH) \
|
||||
$(NULL)
|
||||
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
|
||||
|
||||
+13
-13
@@ -83,19 +83,19 @@ CONFIG_FILE = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-k32w06
|
||||
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/k32w/k32w061/
|
||||
SIGN_IMAGE_PATH = $(AbsTopSourceDir)/third_party/nxp/K32W061DK6/tools/imagetool/
|
||||
|
||||
COMMONCFLAGS := \
|
||||
-fdata-sections \
|
||||
-ffunction-sections \
|
||||
-Os \
|
||||
-g \
|
||||
-DCPU_K32W061HN \
|
||||
-DCPU_JN518X \
|
||||
-DCPU_JN518X_REV=2 \
|
||||
-DJENNIC_CHIP_FAMILY_JN518x \
|
||||
-DJENNIC_CHIP_FAMILY_NAME=_JN518x \
|
||||
-DSDK_DEBUGCONSOLE=0 \
|
||||
-D$(CONFIG_FILE) \
|
||||
-DUSE_RTOS=0 \
|
||||
COMMONCFLAGS := \
|
||||
-fdata-sections \
|
||||
-ffunction-sections \
|
||||
-Os \
|
||||
-g \
|
||||
-DCPU_K32W061HN \
|
||||
-DCPU_JN518X \
|
||||
-DCPU_JN518X_REV=2 \
|
||||
-DJENNIC_CHIP_FAMILY_JN518x \
|
||||
-DJENNIC_CHIP_FAMILY_NAME=_JN518x \
|
||||
-DSDK_DEBUGCONSOLE=0 \
|
||||
-D$(CONFIG_FILE) \
|
||||
-imacros "$(AbsTopSourceDir)/examples/platforms/k32w/k32w061/k32w061-sdk-config.h" \
|
||||
-I$(CONFIG_FILE_PATH) \
|
||||
$(NULL)
|
||||
|
||||
|
||||
@@ -66,13 +66,22 @@ LIB_FLAGS
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/XCVR/DK6/Build/Include \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/XCVR/DK6 \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/Common \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/ \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Interface/ \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Interface \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/SerialManager/Source \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/TimersManager/Source \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Include \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface \
|
||||
-I$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal \
|
||||
-Wno-unknown-pragmas \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-function \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-empty-body \
|
||||
-Wno-missing-field-initializers \
|
||||
-Wno-clobbered \
|
||||
-fno-strict-aliasing \
|
||||
$(NULL)
|
||||
|
||||
@@ -87,7 +96,6 @@ libopenthread_jn5189_plat_a_CPPFLAGS
|
||||
PLATFORM_SOURCES = \
|
||||
src/alarm.c \
|
||||
src/diag.c \
|
||||
src/flash.c \
|
||||
src/logging.c \
|
||||
src/misc.c \
|
||||
src/radio.c \
|
||||
@@ -123,6 +131,12 @@ libopenthread_jn5189_sdk_a_SOURCES
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/devices/JN5189/utilities/debug_console/fsl_debug_console.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/devices/JN5189/utilities/str/fsl_str.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/Common/MicroInt_arm_sdk2.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/Reset/Reset.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Source/MemManager.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/pdm_port.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.c \
|
||||
@top_builddir@/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_jn5189_plat_a_SOURCES = \
|
||||
|
||||
@@ -35,6 +35,7 @@ LDADD_COMMON
|
||||
$(top_builddir)/examples/platforms/k32w/libopenthread-jn5189_sdk.a \
|
||||
$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/ieee-802.15.4/lib/libMiniMac.a \
|
||||
$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/XCVR/lib/libRadio.a \
|
||||
$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Library/libPDM.a \
|
||||
$(NULL)
|
||||
|
||||
LDFLAGS_COMMON += \
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef JN5189_SDK_CONFIG_H
|
||||
#define JN5189_SDK_CONFIG_H
|
||||
|
||||
#ifndef gUsePdm_d
|
||||
#define gUsePdm_d 1
|
||||
#endif
|
||||
|
||||
#ifndef gPdmMemPoolId_c
|
||||
#define gPdmMemPoolId_c 0
|
||||
#endif
|
||||
|
||||
#ifndef gPdmNbSegments
|
||||
#define gPdmNbSegments 63 /* number of sectors contained in PDM storage */
|
||||
#endif
|
||||
|
||||
#ifndef USE_RTOS
|
||||
#define USE_RTOS 0
|
||||
#endif
|
||||
|
||||
#ifndef PoolsDetails_c
|
||||
#define PoolsDetails_c \
|
||||
_block_size_ 512 _number_of_blocks_ 2 _pool_id_(0) _eol_ _block_size_ 768 _number_of_blocks_ 1 _pool_id_(0) _eol_
|
||||
#endif
|
||||
|
||||
#endif // JN5189_SDK_CONFIG_H
|
||||
@@ -69,10 +69,10 @@ m_fsl_prodInfo_size = m_sector_size;
|
||||
m_fsl_prodInfo_end = m_flash_size - 17 * m_sector_size - 1;
|
||||
m_fsl_prodInfo_start = m_fsl_prodInfo_end - m_fsl_prodInfo_size + 1;
|
||||
|
||||
NV_STORAGE_MAX_SECTORS = 64;
|
||||
NV_STORAGE_MAX_SECTORS = 63;
|
||||
NV_STORAGE_SIZE = NV_STORAGE_MAX_SECTORS * m_sector_size;
|
||||
NV_STORAGE_END_ADDRESS = m_fsl_prodInfo_start - 1;
|
||||
NV_STORAGE_START_ADDRESS = NV_STORAGE_END_ADDRESS - NV_STORAGE_SIZE + 1;
|
||||
NV_STORAGE_START_ADDRESS = m_flash_size - 17 * m_sector_size - 1;
|
||||
NV_STORAGE_END_ADDRESS = NV_STORAGE_START_ADDRESS - NV_STORAGE_SIZE + 1;
|
||||
|
||||
INT_STORAGE_END = NV_STORAGE_START_ADDRESS - 1;
|
||||
INT_STORAGE_START = 0x48000;
|
||||
@@ -288,8 +288,8 @@ SECTIONS
|
||||
_end_boot_resume_stack = .;
|
||||
} > RAM0
|
||||
|
||||
__nv_storage_end_address = NV_STORAGE_END_ADDRESS;
|
||||
__nv_storage_start_address = NV_STORAGE_START_ADDRESS;
|
||||
__nv_storage_end_address = NV_STORAGE_START_ADDRESS;
|
||||
__nv_storage_start_address = NV_STORAGE_END_ADDRESS;
|
||||
|
||||
PROVIDE(_vStackTop = __top_RAM0 - 32);
|
||||
PROVIDE(__mac_buffer_base = (__mac_buffer_start & 0xfffe0000));
|
||||
@@ -301,4 +301,4 @@ SECTIONS
|
||||
|
||||
__StackLimit = _vStackTop - STACK_SIZE;
|
||||
ASSERT(__StackLimit >= _end_boot_resume_stack, "Possible stack corruption with data/bss/boot_stack")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
* Define to 1 if you want to use JN589 Flash implementation.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_SETTINGS_RAM 1
|
||||
#define OPENTHREAD_SETTINGS_RAM 0
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE
|
||||
|
||||
@@ -67,14 +67,23 @@ LIB_FLAGS
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/XCVR/DK6/Build/Include \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/XCVR/DK6 \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/Common/ \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/ \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Interface/ \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Interface \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/SerialManager/Source \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/TimersManager/Source \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Include \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal \
|
||||
-I$(top_srcdir)/third_party/nxp/K32W061DK6/boards/k32w061dk6/wireless_examples/openthread/enablement \
|
||||
-Wno-unknown-pragmas \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-function \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-empty-body \
|
||||
-Wno-missing-field-initializers \
|
||||
-Wno-clobbered \
|
||||
-fno-strict-aliasing \
|
||||
$(NULL)
|
||||
|
||||
@@ -89,7 +98,6 @@ libopenthread_k32w061_plat_a_CPPFLAGS
|
||||
PLATFORM_SOURCES = \
|
||||
src/alarm.c \
|
||||
src/diag.c \
|
||||
src/flash.c \
|
||||
src/logging.c \
|
||||
src/misc.c \
|
||||
src/radio.c \
|
||||
@@ -125,6 +133,12 @@ libopenthread_k32w061_sdk_a_SOURCES
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/devices/K32W061/utilities/debug_console/fsl_debug_console.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/devices/K32W061/utilities/str/fsl_str.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/Common/MicroInt_arm_sdk2.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/Reset/Reset.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Source/MemManager.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/pdm_port.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.c \
|
||||
@top_builddir@/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_k32w061_plat_a_SOURCES = \
|
||||
|
||||
@@ -36,6 +36,7 @@ LDADD_COMMON
|
||||
$(top_builddir)/examples/platforms/k32w/libopenthread-k32w061_sdk.a \
|
||||
$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/ieee-802.15.4/lib/libMiniMac.a \
|
||||
$(top_srcdir)/third_party/nxp/K32W061DK6/middleware/wireless/framework/XCVR/lib/libRadio.a \
|
||||
$(top_srcdir)/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Library/libPDM.a \
|
||||
$(NULL)
|
||||
|
||||
LDFLAGS_COMMON += \
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef K32W061_SDK_CONFIG_H
|
||||
#define K32W061_SDK_CONFIG_H
|
||||
|
||||
#ifndef gUsePdm_d
|
||||
#define gUsePdm_d 1
|
||||
#endif
|
||||
|
||||
#ifndef gPdmMemPoolId_c
|
||||
#define gPdmMemPoolId_c 0
|
||||
#endif
|
||||
|
||||
#ifndef gPdmNbSegments
|
||||
#define gPdmNbSegments 63 /* number of sectors contained in PDM storage */
|
||||
#endif
|
||||
|
||||
#ifndef USE_RTOS
|
||||
#define USE_RTOS 0
|
||||
#endif
|
||||
|
||||
#ifndef PoolsDetails_c
|
||||
#define PoolsDetails_c \
|
||||
_block_size_ 512 _number_of_blocks_ 2 _pool_id_(0) _eol_ _block_size_ 768 _number_of_blocks_ 1 _pool_id_(0) _eol_
|
||||
#endif
|
||||
|
||||
#endif // K32W061_SDK_CONFIG_H
|
||||
@@ -69,10 +69,10 @@ m_fsl_prodInfo_size = m_sector_size;
|
||||
m_fsl_prodInfo_end = m_flash_size - 17 * m_sector_size - 1;
|
||||
m_fsl_prodInfo_start = m_fsl_prodInfo_end - m_fsl_prodInfo_size + 1;
|
||||
|
||||
NV_STORAGE_MAX_SECTORS = 64;
|
||||
NV_STORAGE_MAX_SECTORS = 63;
|
||||
NV_STORAGE_SIZE = NV_STORAGE_MAX_SECTORS * m_sector_size;
|
||||
NV_STORAGE_END_ADDRESS = m_fsl_prodInfo_start - 1;
|
||||
NV_STORAGE_START_ADDRESS = NV_STORAGE_END_ADDRESS - NV_STORAGE_SIZE + 1;
|
||||
NV_STORAGE_START_ADDRESS = m_flash_size - 17 * m_sector_size - 1;
|
||||
NV_STORAGE_END_ADDRESS = NV_STORAGE_START_ADDRESS - NV_STORAGE_SIZE + 1;
|
||||
|
||||
INT_STORAGE_END = NV_STORAGE_START_ADDRESS - 1;
|
||||
INT_STORAGE_START = 0x48000;
|
||||
@@ -288,8 +288,8 @@ SECTIONS
|
||||
_end_boot_resume_stack = .;
|
||||
} > RAM0
|
||||
|
||||
__nv_storage_end_address = NV_STORAGE_END_ADDRESS;
|
||||
__nv_storage_start_address = NV_STORAGE_START_ADDRESS;
|
||||
__nv_storage_end_address = NV_STORAGE_START_ADDRESS;
|
||||
__nv_storage_start_address = NV_STORAGE_END_ADDRESS;
|
||||
|
||||
PROVIDE(_vStackTop = __top_RAM0 - 32);
|
||||
PROVIDE(__mac_buffer_base = (__mac_buffer_start & 0xfffe0000));
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
* Define to 1 if you want to use K32W061 Flash implementation.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_SETTINGS_RAM 1
|
||||
#define OPENTHREAD_SETTINGS_RAM 0
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE
|
||||
|
||||
Executable → Regular
+82
-495
@@ -37,353 +37,67 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/platform/settings.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#include "openthread/platform/flash.h"
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "PDM.h"
|
||||
|
||||
#define OT_FLASH_BLOCK_ADD_BEGIN_FLAG (1 << 0)
|
||||
#define OT_FLASH_BLOCK_ADD_COMPLETE_FLAG (1 << 1)
|
||||
#define OT_FLASH_BLOCK_DELETE_FLAG (1 << 2)
|
||||
#define OT_FLASH_BLOCK_INDEX_0_FLAG (1 << 3)
|
||||
/* Compact flag is used to indicate that the next settings block follows at the next 16 bytes
|
||||
* aligned address after the data portion of the current one. Otherwise the next block will be
|
||||
* placed in the next flash page */
|
||||
#define OT_FLASH_BLOCK_COMPACT_FLAG (1 << 4)
|
||||
#define pdmBufferSize 512
|
||||
#define NVM_START_ID 0x4F00
|
||||
|
||||
#define OT_SETTINGS_FLAG_SIZE 16
|
||||
#define OT_SETTINGS_BLOCK_DATA_SIZE 256
|
||||
/* WARNING - the defines below must be in sync with OT NVM datasets from Settings.hpp */
|
||||
#define NVM_MAX_ID 7
|
||||
|
||||
/* K32W erases the flash to value 0x00 */
|
||||
#define FLASH_ERASE_VALUE 0x00
|
||||
#define FLASH_ALIGN_SIZE 16
|
||||
#define FLASH_BLOCK_PAD1_SIZE 10
|
||||
#define FLASH_BLOCK_PAD2_SIZE 15
|
||||
static uint8_t sPdmBuffer[pdmBufferSize] __attribute__((aligned(4))) = {0};
|
||||
|
||||
#define OT_SETTINGS_IN_USE 0xbe5cc5ee
|
||||
|
||||
extern otError utilsFlashErasePage(uint32_t aAddress);
|
||||
|
||||
/* Added padding to make settings block structure align to minimum flash write size of 16 bytes.
|
||||
* The delFlag field has an offset of 16 bytes from the beginning of the structure to allow a new
|
||||
* write on the field. */
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct settingsBlock
|
||||
{
|
||||
uint16_t key;
|
||||
uint16_t flag;
|
||||
uint16_t length;
|
||||
uint8_t padding1[FLASH_BLOCK_PAD1_SIZE];
|
||||
uint8_t delFlag;
|
||||
uint8_t padding2[FLASH_BLOCK_PAD2_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* @def SETTINGS_CONFIG_BASE_ADDRESS
|
||||
*
|
||||
* The base address of settings.
|
||||
*
|
||||
*/
|
||||
#ifndef SETTINGS_CONFIG_BASE_ADDRESS
|
||||
#define SETTINGS_CONFIG_BASE_ADDRESS 0
|
||||
#endif // SETTINGS_CONFIG_BASE_ADDRESS
|
||||
|
||||
/**
|
||||
* @def SETTINGS_CONFIG_PAGE_SIZE
|
||||
*
|
||||
* The page size of settings.
|
||||
*
|
||||
*/
|
||||
#ifndef SETTINGS_CONFIG_PAGE_SIZE
|
||||
#define SETTINGS_CONFIG_PAGE_SIZE 0x800
|
||||
#endif // SETTINGS_CONFIG_PAGE_SIZE
|
||||
|
||||
/**
|
||||
* @def SETTINGS_CONFIG_PAGE_NUM
|
||||
*
|
||||
* The page number of settings.
|
||||
*
|
||||
*/
|
||||
#ifndef SETTINGS_CONFIG_PAGE_NUM
|
||||
#define SETTINGS_CONFIG_PAGE_NUM 2
|
||||
#endif // SETTINGS_CONFIG_PAGE_NUM
|
||||
|
||||
#if (SETTINGS_CONFIG_PAGE_NUM <= 1)
|
||||
#error "Invalid value for `SETTINGS_CONFIG_PAGE_NUM` (should be >= 2)"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def FLASH_ERASE_VALUE
|
||||
*
|
||||
* The value a byte in flash takes after an erase operation.
|
||||
*
|
||||
*/
|
||||
#ifndef FLASH_ERASE_VALUE
|
||||
#define FLASH_ERASE_VALUE 0xFF
|
||||
#endif // FLASH_ERASE_VALUE
|
||||
|
||||
/* macros for setting/clearing bits in a flash byte depending on flash erase value */
|
||||
#if (FLASH_ERASE_VALUE == 0xFF)
|
||||
#define SET_FLASH_BLOCK_FLAG(aVar, aFlag) ((aVar) &= (~(aFlag)))
|
||||
#define FLASH_BLOCK_FLAG_IS_SET(aVar, aFlag) (!((aVar) & (aFlag)))
|
||||
|
||||
#else
|
||||
// FLASH_ERASE_VALUE = 0x00
|
||||
#define SET_FLASH_BLOCK_FLAG(aVar, aFlag) ((aVar) |= (aFlag))
|
||||
#define FLASH_BLOCK_FLAG_IS_SET(aVar, aFlag) ((aVar) & (aFlag))
|
||||
|
||||
#endif
|
||||
|
||||
static uint32_t sSettingsBaseAddress;
|
||||
static uint32_t sSettingsUsedSize;
|
||||
static uint32_t sSettingsPageNum;
|
||||
|
||||
/* linker file symbol for the number of flash sectors used for NVM */
|
||||
extern uint32_t NV_STORAGE_MAX_SECTORS;
|
||||
extern uint8_t pageBuffer[];
|
||||
|
||||
/**
|
||||
* Calculates the aligned length of data for current settings block based on Compact flag
|
||||
*
|
||||
* @param[in] currentPos Offset from the beginning of settings base address where the current
|
||||
* block is located
|
||||
* @param[in] blockFlag Settings block flags value
|
||||
* @param[in] length Length of current block data
|
||||
|
||||
* @return uint16_t Length of aligned data
|
||||
*/
|
||||
static uint16_t getAlignLength(uint16_t currentPos, uint8_t blockFlag, uint16_t length)
|
||||
{
|
||||
uint16_t alignLen;
|
||||
/* in case the compact flag is set length is calculated based on real one aligned to
|
||||
* FLASH_ALIGN_SIZE(16 in this case) */
|
||||
if (FLASH_BLOCK_FLAG_IS_SET(blockFlag, OT_FLASH_BLOCK_COMPACT_FLAG))
|
||||
{
|
||||
alignLen = (length + 1) & 0xfffe;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if the block is not compacted the length will be calculated so that the next block starts
|
||||
* in the next flash page */
|
||||
uint16_t pageOffset = currentPos % SETTINGS_CONFIG_PAGE_SIZE;
|
||||
alignLen = SETTINGS_CONFIG_PAGE_SIZE - pageOffset - sizeof(struct settingsBlock);
|
||||
}
|
||||
|
||||
return alignLen;
|
||||
}
|
||||
|
||||
static void setSettingsFlag(uint32_t aBase, uint32_t aFlag)
|
||||
{
|
||||
otPlatFlashWrite(0, 0, aBase, (uint8_t *)&aFlag, sizeof(aFlag));
|
||||
}
|
||||
|
||||
static void eraseSettings(uint32_t aBase)
|
||||
{
|
||||
uint32_t address = aBase;
|
||||
uint32_t settingsSize = SETTINGS_CONFIG_PAGE_SIZE * sSettingsPageNum / 2;
|
||||
|
||||
while (address < (aBase + settingsSize))
|
||||
{
|
||||
utilsFlashErasePage(address);
|
||||
address += SETTINGS_CONFIG_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static void initSettings(uint32_t aBase, uint32_t aFlag)
|
||||
{
|
||||
eraseSettings(aBase);
|
||||
setSettingsFlag(aBase, aFlag);
|
||||
}
|
||||
|
||||
static uint32_t swapSettingsBlock(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
uint32_t oldBase = sSettingsBaseAddress;
|
||||
uint32_t swapAddress = oldBase;
|
||||
uint32_t usedSize = sSettingsUsedSize;
|
||||
uint32_t settingsSize = SETTINGS_CONFIG_PAGE_SIZE * sSettingsPageNum / 2;
|
||||
bool pageBufferUsed = true;
|
||||
uint8_t tempFlag;
|
||||
|
||||
/* New settings base address */
|
||||
sSettingsBaseAddress =
|
||||
(swapAddress == SETTINGS_CONFIG_BASE_ADDRESS) ? (swapAddress + settingsSize) : SETTINGS_CONFIG_BASE_ADDRESS;
|
||||
|
||||
/* Erase new settings */
|
||||
eraseSettings(sSettingsBaseAddress);
|
||||
/* Erase the page buffer used to accumulate data that will be written to a flash page once it is
|
||||
* full */
|
||||
memset(pageBuffer, FLASH_ERASE_VALUE, SETTINGS_CONFIG_PAGE_SIZE);
|
||||
|
||||
*((uint32_t *)pageBuffer) = OT_SETTINGS_IN_USE;
|
||||
sSettingsUsedSize = OT_SETTINGS_FLAG_SIZE;
|
||||
swapAddress += OT_SETTINGS_FLAG_SIZE;
|
||||
|
||||
while (swapAddress < (oldBase + usedSize))
|
||||
{
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct addSettingsBlock
|
||||
{
|
||||
struct settingsBlock block;
|
||||
uint8_t data[OT_SETTINGS_BLOCK_DATA_SIZE];
|
||||
} OT_TOOL_PACKED_END addBlock;
|
||||
bool valid = true;
|
||||
|
||||
otPlatFlashRead(aInstance, 0, swapAddress, (uint8_t *)(&addBlock.block), sizeof(struct settingsBlock));
|
||||
swapAddress += sizeof(struct settingsBlock);
|
||||
tempFlag = addBlock.block.flag;
|
||||
|
||||
if ((FLASH_BLOCK_FLAG_IS_SET(addBlock.block.flag, OT_FLASH_BLOCK_ADD_COMPLETE_FLAG)) &&
|
||||
(0 == FLASH_BLOCK_FLAG_IS_SET(addBlock.block.delFlag, OT_FLASH_BLOCK_DELETE_FLAG)))
|
||||
|
||||
{
|
||||
uint32_t address = swapAddress + getAlignLength(swapAddress - sizeof(struct settingsBlock),
|
||||
addBlock.block.flag, addBlock.block.length);
|
||||
|
||||
while (address < (oldBase + usedSize))
|
||||
{
|
||||
struct settingsBlock block;
|
||||
|
||||
otPlatFlashRead(aInstance, 0, address, (uint8_t *)(&block), sizeof(block));
|
||||
|
||||
if ((FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_ADD_COMPLETE_FLAG)) &&
|
||||
(0 == FLASH_BLOCK_FLAG_IS_SET(block.delFlag, OT_FLASH_BLOCK_DELETE_FLAG)) &&
|
||||
(FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_INDEX_0_FLAG)) &&
|
||||
(block.key == addBlock.block.key))
|
||||
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
address += (getAlignLength(address, block.flag, block.length) + sizeof(struct settingsBlock));
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
/* Calculate the size of data(block + settings data) that will be written to the
|
||||
* page buffer */
|
||||
uint32_t writeSize = sizeof(struct settingsBlock);
|
||||
|
||||
if (!FLASH_BLOCK_FLAG_IS_SET(addBlock.block.flag, OT_FLASH_BLOCK_COMPACT_FLAG))
|
||||
{
|
||||
/* Once a swap is initiated every settings block is compacted in the new flash
|
||||
* region */
|
||||
SET_FLASH_BLOCK_FLAG(addBlock.block.flag, OT_FLASH_BLOCK_COMPACT_FLAG);
|
||||
}
|
||||
|
||||
/* current pos parameter doesn't count in this case */
|
||||
writeSize += getAlignLength(0, OT_FLASH_BLOCK_COMPACT_FLAG, addBlock.block.length);
|
||||
|
||||
otPlatFlashRead(aInstance, 0, swapAddress, addBlock.data, addBlock.block.length);
|
||||
/* contents fits in current page - we can copy it to page buffer until there is
|
||||
* enough data to program a page */
|
||||
if ((sSettingsUsedSize % SETTINGS_CONFIG_PAGE_SIZE) + writeSize <= SETTINGS_CONFIG_PAGE_SIZE)
|
||||
{
|
||||
pageBufferUsed = false;
|
||||
memcpy(pageBuffer + (sSettingsUsedSize % SETTINGS_CONFIG_PAGE_SIZE), (uint8_t *)(&addBlock),
|
||||
writeSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Page buffer is full and can be written to a flash page */
|
||||
pageBufferUsed = true;
|
||||
|
||||
uint32_t remPageSize = SETTINGS_CONFIG_PAGE_SIZE - (sSettingsUsedSize % SETTINGS_CONFIG_PAGE_SIZE);
|
||||
memcpy(pageBuffer + (sSettingsUsedSize % SETTINGS_CONFIG_PAGE_SIZE), (uint8_t *)(&addBlock),
|
||||
remPageSize);
|
||||
|
||||
/* calculate page address that we are going to write */
|
||||
uint32_t alignAddress = sSettingsBaseAddress + sSettingsUsedSize;
|
||||
alignAddress = alignAddress - (alignAddress % SETTINGS_CONFIG_PAGE_SIZE);
|
||||
otPlatFlashWrite(aInstance, 0, alignAddress, pageBuffer, SETTINGS_CONFIG_PAGE_SIZE);
|
||||
|
||||
/* After the page buffer is erased copy what dind't fit the previous page */
|
||||
memset(pageBuffer, FLASH_ERASE_VALUE, SETTINGS_CONFIG_PAGE_SIZE);
|
||||
memcpy(pageBuffer, (uint8_t *)(&addBlock) + remPageSize, writeSize - remPageSize);
|
||||
}
|
||||
|
||||
sSettingsUsedSize += writeSize;
|
||||
}
|
||||
}
|
||||
else if (addBlock.block.flag == FLASH_ERASE_VALUE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
swapAddress += getAlignLength(swapAddress - sizeof(struct settingsBlock), tempFlag, addBlock.block.length);
|
||||
}
|
||||
|
||||
if (false == pageBufferUsed)
|
||||
{
|
||||
/* If the page buffer has been used and it's not full write to flash at the end */
|
||||
uint32_t alignAddr = sSettingsBaseAddress + sSettingsUsedSize;
|
||||
alignAddr = alignAddr - (alignAddr % SETTINGS_CONFIG_PAGE_SIZE);
|
||||
otPlatFlashWrite(aInstance, 0, alignAddr, pageBuffer, SETTINGS_CONFIG_PAGE_SIZE);
|
||||
}
|
||||
/* Clear the old settings zone */
|
||||
eraseSettings(oldBase);
|
||||
|
||||
return settingsSize - sSettingsUsedSize;
|
||||
}
|
||||
static otError addSetting(otInstance * aInstance,
|
||||
uint16_t aKey,
|
||||
bool aIndex0,
|
||||
const uint8_t *aValue,
|
||||
uint16_t aValueLength);
|
||||
|
||||
static otError addSetting(otInstance * aInstance,
|
||||
uint16_t aKey,
|
||||
bool aIndex0,
|
||||
const uint8_t *aValue,
|
||||
uint16_t aValueLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct addSettingsBlock
|
||||
{
|
||||
struct settingsBlock block;
|
||||
uint8_t data[OT_SETTINGS_BLOCK_DATA_SIZE];
|
||||
} OT_TOOL_PACKED_END addBlock;
|
||||
uint32_t settingsSize = SETTINGS_CONFIG_PAGE_SIZE * sSettingsPageNum / 2;
|
||||
|
||||
/* Add all the settings flags once and optimize for one write to flash */
|
||||
addBlock.block.flag = FLASH_ERASE_VALUE;
|
||||
addBlock.block.delFlag = FLASH_ERASE_VALUE;
|
||||
addBlock.block.key = aKey;
|
||||
memset(addBlock.block.padding1, FLASH_ERASE_VALUE, FLASH_BLOCK_PAD1_SIZE);
|
||||
memset(addBlock.block.padding2, FLASH_ERASE_VALUE, FLASH_BLOCK_PAD2_SIZE);
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
PDM_teStatus pdmStatus;
|
||||
uint16_t bytesRead;
|
||||
|
||||
otEXPECT_ACTION((pdmBufferSize > aValueLength + sizeof(uint16_t)), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
if (aIndex0)
|
||||
{
|
||||
SET_FLASH_BLOCK_FLAG(addBlock.block.flag, OT_FLASH_BLOCK_INDEX_0_FLAG);
|
||||
/* save the lenght of the first record element at the start of the record so we can know
|
||||
if the record contains multiple entries of a size or just a single entry */
|
||||
memcpy(sPdmBuffer, (uint8_t *)&aValueLength, sizeof(uint16_t));
|
||||
memcpy(sPdmBuffer + sizeof(uint16_t), (uint8_t *)aValue, aValueLength);
|
||||
|
||||
pdmStatus = PDM_eSaveRecordData(aKey + NVM_START_ID, sPdmBuffer, aValueLength + sizeof(uint16_t));
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NO_BUFS);
|
||||
}
|
||||
|
||||
SET_FLASH_BLOCK_FLAG(addBlock.block.flag, OT_FLASH_BLOCK_ADD_BEGIN_FLAG);
|
||||
addBlock.block.length = aValueLength;
|
||||
|
||||
if ((sSettingsUsedSize + getAlignLength(sSettingsUsedSize, addBlock.block.flag, addBlock.block.length) +
|
||||
sizeof(struct settingsBlock)) >= settingsSize)
|
||||
else
|
||||
{
|
||||
otEXPECT_ACTION(swapSettingsBlock(aInstance) >=
|
||||
(getAlignLength(sSettingsUsedSize, addBlock.block.flag, addBlock.block.length) +
|
||||
sizeof(struct settingsBlock)),
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
pdmStatus = PDM_eReadDataFromRecord(aKey + NVM_START_ID, sPdmBuffer, pdmBufferSize, &bytesRead);
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NOT_FOUND);
|
||||
otEXPECT_ACTION((pdmBufferSize > aValueLength + bytesRead), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
memcpy(sPdmBuffer + bytesRead, (uint8_t *)aValue, aValueLength);
|
||||
|
||||
pdmStatus = PDM_eSaveRecordData(aKey + NVM_START_ID, sPdmBuffer, aValueLength + bytesRead);
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NO_BUFS);
|
||||
}
|
||||
|
||||
memset(addBlock.data, FLASH_ERASE_VALUE, OT_SETTINGS_BLOCK_DATA_SIZE);
|
||||
memcpy(addBlock.data, aValue, addBlock.block.length);
|
||||
|
||||
SET_FLASH_BLOCK_FLAG(addBlock.block.flag, OT_FLASH_BLOCK_ADD_COMPLETE_FLAG);
|
||||
otPlatFlashWrite(aInstance, 0, sSettingsBaseAddress + sSettingsUsedSize, (uint8_t *)(&addBlock.block),
|
||||
sizeof(struct settingsBlock) + addBlock.block.length);
|
||||
/* The next settings block will be written to the next flash page to optimize the number of
|
||||
* writes made to a page */
|
||||
sSettingsUsedSize +=
|
||||
(sizeof(struct settingsBlock) + getAlignLength(sSettingsUsedSize, addBlock.block.flag, addBlock.block.length));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -392,52 +106,7 @@ exit:
|
||||
void otPlatSettingsInit(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
uint8_t index;
|
||||
struct settingsBlock block;
|
||||
|
||||
/* exported symbol from linker file */
|
||||
sSettingsPageNum = (uint32_t)&NV_STORAGE_MAX_SECTORS;
|
||||
uint32_t settingsSize = SETTINGS_CONFIG_PAGE_SIZE * sSettingsPageNum / 2;
|
||||
|
||||
sSettingsBaseAddress = SETTINGS_CONFIG_BASE_ADDRESS;
|
||||
|
||||
otPlatFlashInit(aInstance);
|
||||
|
||||
for (index = 0; index < 2; index++)
|
||||
{
|
||||
uint32_t blockFlag;
|
||||
|
||||
sSettingsBaseAddress += settingsSize * index;
|
||||
otPlatFlashRead(aInstance, 0, sSettingsBaseAddress, (uint8_t *)(&blockFlag), sizeof(blockFlag));
|
||||
|
||||
if (blockFlag == OT_SETTINGS_IN_USE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 2)
|
||||
{
|
||||
initSettings(sSettingsBaseAddress, (uint32_t)OT_SETTINGS_IN_USE);
|
||||
}
|
||||
|
||||
sSettingsUsedSize = OT_SETTINGS_FLAG_SIZE;
|
||||
|
||||
while (sSettingsUsedSize < settingsSize)
|
||||
{
|
||||
otPlatFlashRead(aInstance, 0, sSettingsBaseAddress + sSettingsUsedSize, (uint8_t *)(&block), sizeof(block));
|
||||
|
||||
if (FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_ADD_BEGIN_FLAG))
|
||||
{
|
||||
sSettingsUsedSize +=
|
||||
(getAlignLength(sSettingsUsedSize, block.flag, block.length) + sizeof(struct settingsBlock));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void)PDM_Init();
|
||||
}
|
||||
|
||||
void otPlatSettingsDeinit(otInstance *aInstance)
|
||||
@@ -445,84 +114,38 @@ void otPlatSettingsDeinit(otInstance *aInstance)
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
}
|
||||
|
||||
otError otPlatSettingsBeginChange(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatSettingsCommitChange(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatSettingsAbandonChange(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NOT_FOUND;
|
||||
uint32_t address = sSettingsBaseAddress + OT_SETTINGS_FLAG_SIZE;
|
||||
uint16_t valueLength = 0;
|
||||
int index = 0;
|
||||
otError error = OT_ERROR_NONE;
|
||||
PDM_teStatus pdmStatus;
|
||||
uint16_t bytesRead = 0;
|
||||
uint16_t offset = 0;
|
||||
|
||||
while (address < (sSettingsBaseAddress + sSettingsUsedSize))
|
||||
// only perform read if an input buffer was passed in
|
||||
if (aValue != NULL && aValueLength != NULL)
|
||||
{
|
||||
struct settingsBlock block;
|
||||
offset = aIndex * (*aValueLength);
|
||||
pdmStatus = PDM_eReadPartialDataFromExistingRecord(aKey + NVM_START_ID, offset + sizeof(uint16_t), aValue,
|
||||
*aValueLength, &bytesRead);
|
||||
|
||||
otPlatFlashRead(aInstance, 0, address, (uint8_t *)(&block), sizeof(block));
|
||||
|
||||
if (block.key == aKey)
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NOT_FOUND);
|
||||
*aValueLength = bytesRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (false == PDM_bDoesDataExist(aKey + NVM_START_ID, &bytesRead))
|
||||
{
|
||||
if (FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_INDEX_0_FLAG))
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
if ((FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_ADD_COMPLETE_FLAG)) &&
|
||||
(0 == FLASH_BLOCK_FLAG_IS_SET(block.delFlag, OT_FLASH_BLOCK_DELETE_FLAG)))
|
||||
{
|
||||
if (index == aIndex)
|
||||
{
|
||||
uint16_t readLength = block.length;
|
||||
|
||||
// only perform read if an input buffer was passed in
|
||||
if (aValue != NULL && aValueLength != NULL)
|
||||
{
|
||||
// adjust read length if input buffer length is smaller
|
||||
if (readLength > *aValueLength)
|
||||
{
|
||||
readLength = *aValueLength;
|
||||
}
|
||||
|
||||
otPlatFlashRead(aInstance, 0, address + sizeof(struct settingsBlock), aValue, readLength);
|
||||
}
|
||||
|
||||
valueLength = block.length;
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
error = OT_ERROR_NOT_FOUND;
|
||||
}
|
||||
else if (aValueLength != NULL)
|
||||
{
|
||||
*aValueLength = bytesRead;
|
||||
}
|
||||
|
||||
address += (getAlignLength(address, block.flag, block.length) + sizeof(struct settingsBlock));
|
||||
}
|
||||
|
||||
if (aValueLength != NULL)
|
||||
{
|
||||
*aValueLength = valueLength;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -544,80 +167,44 @@ otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NOT_FOUND;
|
||||
uint32_t address = sSettingsBaseAddress + OT_SETTINGS_FLAG_SIZE;
|
||||
int index = 0;
|
||||
otError error = OT_ERROR_NONE;
|
||||
PDM_teStatus pdmStatus;
|
||||
uint16_t bytesRead = 0;
|
||||
uint16_t recordElmSize = 0;
|
||||
|
||||
while (address < (sSettingsBaseAddress + sSettingsUsedSize))
|
||||
pdmStatus = PDM_eReadDataFromRecord(aKey + NVM_START_ID, sPdmBuffer, pdmBufferSize, &bytesRead);
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
recordElmSize = *((uint16_t *)sPdmBuffer);
|
||||
|
||||
/* Determine if record contains multiple entries or just one */
|
||||
if ((-1 == aIndex) || (recordElmSize == bytesRead - sizeof(recordElmSize)))
|
||||
{
|
||||
struct settingsBlock block;
|
||||
PDM_vDeleteDataRecord(aKey + NVM_START_ID);
|
||||
}
|
||||
else if (recordElmSize < bytesRead)
|
||||
{
|
||||
uint8_t *pMovePtrDst = sPdmBuffer + sizeof(recordElmSize) + (recordElmSize * aIndex);
|
||||
uint8_t *pMovePtrSrc = pMovePtrDst + recordElmSize;
|
||||
|
||||
otPlatFlashRead(aInstance, 0, address, (uint8_t *)(&block), sizeof(block));
|
||||
|
||||
if (block.key == aKey)
|
||||
if (pMovePtrSrc < sPdmBuffer + bytesRead)
|
||||
{
|
||||
if (FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_INDEX_0_FLAG))
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
if ((FLASH_BLOCK_FLAG_IS_SET(block.flag, OT_FLASH_BLOCK_ADD_COMPLETE_FLAG)) &&
|
||||
(0 == FLASH_BLOCK_FLAG_IS_SET(block.delFlag, OT_FLASH_BLOCK_DELETE_FLAG)))
|
||||
{
|
||||
bool flashWrite = false;
|
||||
|
||||
if (aIndex == index || aIndex == -1)
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
SET_FLASH_BLOCK_FLAG(block.delFlag, OT_FLASH_BLOCK_DELETE_FLAG);
|
||||
flashWrite = true;
|
||||
}
|
||||
|
||||
if (index == 1 && aIndex == 0)
|
||||
{
|
||||
SET_FLASH_BLOCK_FLAG(block.flag, OT_FLASH_BLOCK_INDEX_0_FLAG);
|
||||
flashWrite = true;
|
||||
}
|
||||
|
||||
if (flashWrite)
|
||||
{
|
||||
otPlatFlashWrite(aInstance, 0, address, (uint8_t *)(&block), sizeof(block));
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
memcpy(pMovePtrDst, pMovePtrSrc, recordElmSize);
|
||||
}
|
||||
|
||||
address += (getAlignLength(address, block.flag, block.length) + sizeof(struct settingsBlock));
|
||||
pdmStatus = PDM_eSaveRecordData(aKey + NVM_START_ID, sPdmBuffer, bytesRead - recordElmSize);
|
||||
otEXPECT_ACTION((PDM_E_STATUS_OK == pdmStatus), error = OT_ERROR_NOT_FOUND);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatSettingsWipe(otInstance *aInstance)
|
||||
{
|
||||
uint32_t address = SETTINGS_CONFIG_BASE_ADDRESS;
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
/* Clears all the flash pages during a factory reset */
|
||||
for (uint32_t i = 0; i < sSettingsPageNum; i++)
|
||||
for (uint32_t i = 0; i <= NVM_MAX_ID; i++)
|
||||
{
|
||||
/* This function protects against erasing an already erased page so we can just erase all
|
||||
* pages to have and have all the settings storage clean */
|
||||
utilsFlashErasePage(address);
|
||||
address += SETTINGS_CONFIG_PAGE_SIZE;
|
||||
PDM_vDeleteDataRecord(NVM_START_ID + i);
|
||||
}
|
||||
|
||||
/* Each time a factory reset is invoked start the settings zone in the alternate region to
|
||||
* maximize wear leveling */
|
||||
if (SETTINGS_CONFIG_BASE_ADDRESS == sSettingsBaseAddress)
|
||||
{
|
||||
sSettingsBaseAddress = SETTINGS_CONFIG_BASE_ADDRESS + (SETTINGS_CONFIG_PAGE_SIZE * sSettingsPageNum / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
sSettingsBaseAddress = SETTINGS_CONFIG_BASE_ADDRESS;
|
||||
}
|
||||
setSettingsFlag(sSettingsBaseAddress, OT_SETTINGS_IN_USE);
|
||||
|
||||
otPlatSettingsInit(aInstance);
|
||||
}
|
||||
|
||||
Executable → Regular
+40
-1
@@ -39,7 +39,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
otInstance *sInstance;
|
||||
#include "MemManager.h"
|
||||
|
||||
otInstance * sInstance;
|
||||
OT_TOOL_WEAK uint32_t gInterruptDisableCount = 0;
|
||||
|
||||
void otSysInit(int argc, char *argv[])
|
||||
{
|
||||
@@ -57,6 +60,7 @@ void otSysInit(int argc, char *argv[])
|
||||
|
||||
BOARD_BootClockRUN();
|
||||
BOARD_InitPins();
|
||||
MEM_Init();
|
||||
}
|
||||
|
||||
K32WAlarmInit();
|
||||
@@ -86,3 +90,38 @@ WEAK void otSysEventSignalPending(void)
|
||||
{
|
||||
/* Intentionally left empty */
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_InterruptEnable
|
||||
* Description : self explanatory.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
OT_TOOL_WEAK void OSA_InterruptEnable(void)
|
||||
{
|
||||
if (gInterruptDisableCount > 0)
|
||||
{
|
||||
gInterruptDisableCount--;
|
||||
|
||||
if (gInterruptDisableCount == 0)
|
||||
{
|
||||
__enable_irq();
|
||||
}
|
||||
/* call core API to enable the global interrupt*/
|
||||
}
|
||||
}
|
||||
|
||||
/*FUNCTION**********************************************************************
|
||||
*
|
||||
* Function Name : OSA_InterruptDisable
|
||||
* Description : self explanatory.
|
||||
*
|
||||
*END**************************************************************************/
|
||||
OT_TOOL_WEAK void OSA_InterruptDisable(void)
|
||||
{
|
||||
/* call core API to disable the global interrupt*/
|
||||
__disable_irq();
|
||||
|
||||
/* update counter*/
|
||||
gInterruptDisableCount++;
|
||||
}
|
||||
|
||||
Vendored
Executable
+822
@@ -0,0 +1,822 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "Flash_Adapter.h"
|
||||
#include "FunctionLib.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#if gNvStorageIncluded_d
|
||||
#include "NVM_Interface.h"
|
||||
#endif
|
||||
#include "Panic.h"
|
||||
#include "fsl_debug_console.h"
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
* Private macros
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
#if (PGM_SIZE_BYTE == 4)
|
||||
#define mProgBuffSizeInPgmWrUnits_c 16
|
||||
#elif (PGM_SIZE_BYTE == 8)
|
||||
#define mProgBuffSizeInPgmWrUnits_c 8
|
||||
#else
|
||||
#define mProgBuffSizeInPgmWrUnits_c 4
|
||||
#endif
|
||||
|
||||
/* Generator for CRC calculations. */
|
||||
#define POLGEN 0x1021
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
#include "rom_psector.h"
|
||||
void ResetMCU(void);
|
||||
#endif
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
static uint32_t NV_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t* pData);
|
||||
#if !defined CPU_QN908X && ! defined CPU_JN518X
|
||||
static uint8_t NV_VerifyCrcOverHWParameters(hardwareParameters_t* pHwParams);
|
||||
static uint16_t NV_ComputeCrcOverHWParameters(hardwareParameters_t* pHwParams);
|
||||
#endif
|
||||
static void NV_Flash_WaitForCSEndAndDisableInterrupts(void);
|
||||
#ifdef CPU_QN908X
|
||||
static uint32_t SwFlashVerifyErase (uint32_t start, uint32_t lengthInBytes);
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/* Hardware parameters */
|
||||
hardwareParameters_t gHardwareParameters;
|
||||
extern flash_config_t gFlashConfig;
|
||||
|
||||
|
||||
#if !defined CPU_QN908X && !defined CPU_JN518X
|
||||
static const uint8_t mProdDataIdentifier[10] = {"PROD_DATA:"};
|
||||
#endif
|
||||
#if (USE_RTOS)
|
||||
static osaSemaphoreId_t mFlashAdapterSemaphoreId;
|
||||
#endif
|
||||
static volatile uint8_t mFA_CSFlag = 0;
|
||||
static volatile uint8_t mFA_SemWaitCount = 0;
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
* Private functions
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
/*! *********************************************************************************
|
||||
* \brief This function ensures that there are no critical sections on and disables interrupts.
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
static void NV_Flash_WaitForCSEndAndDisableInterrupts(void)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
#if (gNvStorageIncluded_d)
|
||||
/*on freeRTOS NvIdle runs on a freeRTOS idle task hook which must never block. In this RTOS at least one task must be ready */
|
||||
/*since NvIdle runs on the task which has the least priority in the system we can wait in a loop for the end of the critical section */
|
||||
osaTaskId_t currentTaskId = OSA_TaskGetId();
|
||||
if(currentTaskId == (osaTaskId_t)NvGetNvIdleTaskId())
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
while (mFA_CSFlag);
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mFA_SemWaitCount++;
|
||||
OSA_InterruptEnable();
|
||||
OSA_SemaphoreWait(mFlashAdapterSemaphoreId, osaWaitForever_c);
|
||||
}
|
||||
}
|
||||
#else
|
||||
OSA_InterruptDisable();
|
||||
#endif
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Write aligned data to FLASH
|
||||
*
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint32_t NV_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t* pData)
|
||||
{
|
||||
uint32_t progBuf[PGM_SIZE_BYTE/sizeof(uint32_t)];
|
||||
uint32_t status = kStatus_FLASH_Success;
|
||||
#if !defined (CPU_JN518X)
|
||||
if( (size & (PGM_SIZE_BYTE - 0x01U)) != 0 )
|
||||
{
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
#if gFlashEraseDuringWrite
|
||||
{
|
||||
NV_FlashEraseSector(dest, size-1);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if( (size & (PGM_SIZE_BYTE - 0x01U)) != 0 )
|
||||
{
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
if( (dest & MASK_LOG(PGM_SIZE_BYTE_LOG)) != 0 )
|
||||
{
|
||||
PRINTF("Unaligned flash address %08lx", dest);
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
|
||||
NV_FlashEraseSector(dest, size-1);
|
||||
#endif
|
||||
|
||||
|
||||
while(size)
|
||||
{
|
||||
FLib_MemCpy(progBuf, pData, PGM_SIZE_BYTE);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
status = FLASH_PROGRAM_AREA(dest, progBuf, PGM_SIZE_BYTE);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
|
||||
if(status != kStatus_FLASH_Success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pData += PGM_SIZE_BYTE;
|
||||
dest += PGM_SIZE_BYTE;
|
||||
size -= PGM_SIZE_BYTE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined CPU_QN908X && ! defined CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief Verifies if the CRC field matches computed CRC over stored values
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return 1 on success, 0 otherwise
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint8_t NV_VerifyCrcOverHWParameters(hardwareParameters_t* pHwParams)
|
||||
{
|
||||
uint8_t status = 0;
|
||||
|
||||
if(NV_ComputeCrcOverHWParameters(pHwParams) == pHwParams->hardwareParamsCrc)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Computes the CRC for the hardware parameters and stores it
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return Computed CRC value.
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint16_t NV_ComputeCrcOverHWParameters(hardwareParameters_t* pHwParams)
|
||||
{
|
||||
uint16_t computedCRC = 0;
|
||||
uint8_t crcA;
|
||||
uint8_t byte = 0;
|
||||
if(NULL != pHwParams)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)(&pHwParams->reserved);
|
||||
uint16_t len = (uint8_t *)(&pHwParams->hardwareParamsCrc) -
|
||||
(uint8_t *)(&pHwParams->reserved);
|
||||
while(len)
|
||||
{
|
||||
byte = *ptr;
|
||||
computedCRC ^= ((uint16_t)byte << 8);
|
||||
for(crcA = 8; crcA; crcA--)
|
||||
{
|
||||
if(computedCRC & 0x8000) {
|
||||
computedCRC <<= 1;
|
||||
computedCRC ^= POLGEN;
|
||||
}
|
||||
else computedCRC <<= 1;
|
||||
}
|
||||
--len;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return computedCRC;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPU_QN908X
|
||||
/*! *********************************************************************************
|
||||
* \brief Flash verify erase software implementation
|
||||
*
|
||||
* \param[in] start - start address of the memory block to be verified
|
||||
* \param[in] lengthInBytes - memory block length
|
||||
*
|
||||
* \return TRUE if the flash memory area is blank (erased), FALSE otherwise
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t SwFlashVerifyErase (uint32_t start, uint32_t lengthInBytes)
|
||||
{
|
||||
uint8_t* pAddress = (uint8_t*)start;
|
||||
flash_status_t status = kStatus_FLASH_Success;
|
||||
|
||||
do
|
||||
{
|
||||
if(*pAddress++ != 0xff)
|
||||
{
|
||||
status = kStatus_FLASH_EraseError;
|
||||
break;
|
||||
}
|
||||
} while(--lengthInBytes);
|
||||
|
||||
return (uint32_t)status;
|
||||
}
|
||||
#endif
|
||||
#ifdef CPU_JN518X
|
||||
#define FLASH_WORD_SZ 16
|
||||
|
||||
/* This is kept as an example of code using the TRY .. CATCH for exceptions
|
||||
* Using it raises some execution issues with a debugger
|
||||
*/
|
||||
uint32_t NV_ReadSweep(uint32_t start_addr, uint32_t end_addr)
|
||||
{
|
||||
uint32_t addr = start_addr;
|
||||
TRY
|
||||
{
|
||||
while (addr < end_addr)
|
||||
{
|
||||
volatile uint32_t read_val;
|
||||
read_val = *(uint32_t*)addr;
|
||||
read_val = read_val;
|
||||
addr += FLASH_WORD_SZ;
|
||||
}
|
||||
}
|
||||
CATCH (BUS_EXCEPTION)
|
||||
{
|
||||
/* return page address if an error is detected */
|
||||
return ROUND_FLOOR(addr, 9);
|
||||
}
|
||||
YRT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t NV_SafeReadFromFlash(uint8_t * ram_dst, uint8_t * flash_src, size_t size)
|
||||
{
|
||||
uint32_t au32Data[FLASH_WORD_SZ/sizeof(uint32_t)];
|
||||
uint32_t st = kStatus_FLASH_Fail;
|
||||
uint32_t nb_flash_words = (size + (FLASH_WORD_SZ-1)) / FLASH_WORD_SZ;
|
||||
while (nb_flash_words-- > 0)
|
||||
{
|
||||
size_t sz;
|
||||
sz = (size >= FLASH_WORD_SZ) ? FLASH_WORD_SZ : size;
|
||||
st = FLASH_Read(FLASH, flash_src, 0, au32Data);
|
||||
if (st != kStatus_FLASH_Success) break;
|
||||
memcpy(ram_dst, (uint8_t*)&au32Data[0], sz);
|
||||
ram_dst += sz;
|
||||
flash_src += sz;
|
||||
size -= sz;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
void NV_FlashPerformAudit(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
uint32_t addr = INT_STORAGE_START_OFFSET;
|
||||
if (INT_STORAGE_END_OFFSET == INT_STORAGE_START_OFFSET) addr++;
|
||||
uint32_t end = (uint32_t)0x9ddff;
|
||||
|
||||
uint32_t failed_addr;
|
||||
uint8_t buf[FLASH_PAGE_SIZE];
|
||||
|
||||
while (addr <= ROUND_FLOOR(end, 9))
|
||||
{
|
||||
status = FLASH_BlankCheck(FLASH, (uint8_t*)addr, (uint8_t*)end);
|
||||
if (kStatus_FLASH_Fail == status)
|
||||
{
|
||||
failed_addr = FLASH->DATAW[0]; /* is a flash word address */
|
||||
failed_addr <<= 4;
|
||||
addr = ROUND_FLOOR(failed_addr, 9);
|
||||
status = NV_SafeReadFromFlash(buf, (uint8_t*)addr, FLASH_PAGE_SIZE);
|
||||
if (kStatus_FLASH_Success != status)
|
||||
{
|
||||
status = FLASH_Erase(FLASH,
|
||||
(uint8_t*)addr,
|
||||
(uint8_t*)(addr+FLASH_PAGE_SIZE-1));
|
||||
if (status != kStatus_FLASH_Success)
|
||||
{
|
||||
PRINTF("NV Audit Erase failed at addr=%08lx\r\n", addr);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
addr += FLASH_PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifdef CPU_JN518X
|
||||
int PsectorUpdateFlashAudit(uint32_t new_value)
|
||||
{
|
||||
int res = 1;
|
||||
psector_page_data_t page_buf;
|
||||
psector_page_data_t *page0 = (psector_page_data_t*)0x9e800;
|
||||
|
||||
memcpy(&page_buf, page0, FLASH_PAGE_SIZE);
|
||||
|
||||
((psector_page_data_t*)&page_buf)->page0_v3.flash_audit_done = new_value;
|
||||
page_buf.hdr.version ++;
|
||||
page_buf.hdr.checksum = psector_CalculateChecksum((psector_page_t *)&page_buf);
|
||||
if (psector_WriteUpdatePage(PSECTOR_PAGE0_PART, (psector_page_t *)&page_buf) != WRITE_OK)
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetMCU(); /* Commit now by forcing reset */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int psector_FlashAudit(void)
|
||||
{
|
||||
int res = -1;
|
||||
do {
|
||||
psector_page_data_t *page0 = (psector_page_data_t*)0x9e800;
|
||||
uint32_t flash_audit_word = page0->page0_v3.flash_audit_done;
|
||||
|
||||
if ((flash_audit_word & 0xffff) == FLASH_AUDIT_DONE)
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to verify internal flash */
|
||||
NV_FlashPerformAudit();
|
||||
uint32_t flash_audit_code = (flash_audit_word & 0xffff0000u) | FLASH_AUDIT_DONE;
|
||||
res = PsectorUpdateFlashAudit(flash_audit_code);
|
||||
if (res < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Initialize the FLASH driver
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Init(void)
|
||||
{
|
||||
static bool_t nvmInit = 0;
|
||||
if(nvmInit == 0)
|
||||
{
|
||||
#ifdef CPU_QN908X
|
||||
/* Configure Flash */
|
||||
FLASH_GetDefaultConfig(&gFlashConfig);
|
||||
gFlashConfig.blockBase = 0x0U;
|
||||
#endif /* CPU_QN908X */
|
||||
#ifdef gNVM_MULTICORE_SUPPORT_d
|
||||
FLASH_SetProperty(&gFlashConfig, kFLASH_PropertyFlashMemoryIndex, 1);
|
||||
#endif
|
||||
/* Init Flash */
|
||||
FLASH_INIT();
|
||||
#if (defined(CPU_MKW36Z512VFP4) || defined(CPU_MKW36Z512VHT4))
|
||||
/* KW36 has 256KB of FlexNVM mapped at adress 0x1000 0000 which also has an alias starting from address 0x0004 0000.
|
||||
* Configured the Flash driver to treat the PFLASH bloxk and FlexNVM block as a continuous memory block. */
|
||||
gFlashConfig.DFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE * FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT;
|
||||
#endif
|
||||
#if (USE_RTOS)
|
||||
if( (mFlashAdapterSemaphoreId = OSA_SemaphoreCreate(0)) == NULL )
|
||||
{
|
||||
panic( ID_PANIC(0,0), (uint32_t)NV_Init, 0, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
if (!nvmInit)
|
||||
{
|
||||
if (psector_FlashAudit() == 0)
|
||||
nvmInit = 1;
|
||||
}
|
||||
#else
|
||||
nvmInit = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* Name: NvSetCriticalSection
|
||||
* Description: enter critical section
|
||||
* Parameters: -
|
||||
* Return: -
|
||||
******************************************************************************/
|
||||
/*! *********************************************************************************
|
||||
* \brief Start a critical section during which flash operations are not allowed
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Flash_SetCriticalSection
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
OSA_InterruptDisable();
|
||||
++mFA_CSFlag;
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Start a critical section during which flash operations are not allowed
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Flash_ClearCriticalSection
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag)
|
||||
{
|
||||
mFA_CSFlag--;
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
while(1)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if(mFA_CSFlag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(mFA_SemWaitCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mFA_SemWaitCount--;
|
||||
OSA_InterruptEnable();
|
||||
OSA_SemaphorePost(mFlashAdapterSemaphoreId);
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Verify erase data in Flash
|
||||
*
|
||||
* \param[in] start The address of the Flash location
|
||||
* \param[in] lengthInBytes The number of bytes to be checked
|
||||
* \param[in] margin
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashVerifyErase ( uint32_t start, uint32_t lengthInBytes)
|
||||
{
|
||||
uint32_t status;
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
|
||||
status = FLASH_VERIFY_ERASE(start, lengthInBytes);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Write aligned data to FLASH
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashProgram(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData)
|
||||
{
|
||||
return NV_FlashProgramAdaptation(dest, size, pData);
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Write data to FLASH
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashProgramUnaligned(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData)
|
||||
{
|
||||
uint8_t buffer[PGM_SIZE_BYTE];
|
||||
uint32_t status;
|
||||
do {
|
||||
uint32_t align_addr = ROUND_FLOOR(dest, PGM_SIZE_BYTE_LOG);
|
||||
uint16_t bytes = (dest - align_addr);
|
||||
|
||||
if( bytes )
|
||||
{
|
||||
uint16_t unalignedBytes = PGM_SIZE_BYTE - bytes;
|
||||
|
||||
if( unalignedBytes > size )
|
||||
{
|
||||
unalignedBytes = size;
|
||||
}
|
||||
|
||||
if (FLib_CopyFromFlash(buffer, (void*)align_addr, PGM_SIZE_BYTE))
|
||||
{
|
||||
PRINTF("Raised error while reading from %08lx\r\n", align_addr);
|
||||
}
|
||||
|
||||
|
||||
FLib_MemCpy(&buffer[bytes], pData, unalignedBytes);
|
||||
|
||||
status = NV_FlashProgramAdaptation(align_addr, PGM_SIZE_BYTE, buffer);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
|
||||
dest += unalignedBytes;
|
||||
/* if size is less than the distance to the end of program block
|
||||
unalignedBytes has been shrunk , after size is decremented it will become 0 */
|
||||
pData += unalignedBytes;
|
||||
size -= unalignedBytes;
|
||||
}
|
||||
|
||||
bytes = size & ~(PGM_SIZE_BYTE - 1U);
|
||||
|
||||
/* Now dest is on an aligned boundary */
|
||||
/* bytes is an integer number of program blocks (pages) */
|
||||
if( bytes )
|
||||
{
|
||||
status = NV_FlashProgramAdaptation(dest, bytes, pData);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
|
||||
dest += bytes;
|
||||
pData += bytes;
|
||||
size -= bytes;
|
||||
}
|
||||
|
||||
/* dest is still aligned because we have increased it by a multiple of the program block (page) */
|
||||
if( size )
|
||||
{
|
||||
if (
|
||||
#ifdef CPU_JN518X
|
||||
/* Avoid reading page if it is blank */
|
||||
(FLASH_VERIFY_ERASE(dest, PGM_SIZE_BYTE) == kStatus_FLASH_Fail) &&
|
||||
#endif
|
||||
(FLib_CopyFromFlash(buffer, (void*)dest, PGM_SIZE_BYTE))
|
||||
)
|
||||
{
|
||||
PRINTF("Raised error while reading from %08lx\r\n", (dest - bytes));
|
||||
}
|
||||
|
||||
FLib_MemCpy(buffer, pData, size);
|
||||
status = NV_FlashProgramAdaptation(dest, PGM_SIZE_BYTE, buffer);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
}
|
||||
status = kStatus_FLASH_Success;
|
||||
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Erase to 0xFF one ore more FLASH sectors.
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The start address of the first sector to be erased
|
||||
* \param[in] size The amount of flash to be erased (multiple of sector size)
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashEraseSector(uint32_t dest, uint32_t size)
|
||||
{
|
||||
uint32_t status;
|
||||
#ifdef CPU_QN908X
|
||||
uint32_t status_flags;
|
||||
#endif
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
#if defined(CPU_QN908X)
|
||||
status_flags = FLASH_GetStatusFlags();
|
||||
if(status_flags & FLASH_INT_STAT_AHBL_INT_MASK)
|
||||
{
|
||||
FLASH_ClearStatusFlags(FLASH_INTCLR_AHBL_INTCLR_MASK);
|
||||
}
|
||||
if(status_flags & FLASH_INT_STAT_AHBH_INT_MASK)
|
||||
{
|
||||
FLASH_ClearStatusFlags(FLASH_INTCLR_AHBH_INTCLR_MASK);
|
||||
}
|
||||
#endif
|
||||
status = FLASH_ERASE_AREA(dest, size);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined CPU_QN908X && !defined CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief Load the HW parameters from Flash to RAM
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure where HW parameters will be stored
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_ReadHWParameters(hardwareParameters_t *pHwParams)
|
||||
{
|
||||
hardwareParameters_t* pLocalParams = (hardwareParameters_t*)FREESCALE_PROD_DATA_BASE_ADDR;
|
||||
uint32_t status = 0;
|
||||
do {
|
||||
|
||||
if(NULL == pHwParams)
|
||||
{
|
||||
/* Invalid parameter */
|
||||
status = 2;
|
||||
break;
|
||||
}
|
||||
#ifdef CPU_JN518X
|
||||
#if 0
|
||||
if (NV_SafeReadFromFlash((uint8_t*)pHwParams,
|
||||
(uint8_t*)pLocalParams,
|
||||
sizeof(hardwareParameters_t)) == kStatus_FLASH_Success)
|
||||
{
|
||||
if (FLib_MemCmp(pHwParams,
|
||||
(void*)mProdDataIdentifier,
|
||||
sizeof(mProdDataIdentifier)) &&
|
||||
NV_VerifyCrcOverHWParameters(pHwParams))
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_FlashEraseSector((uint32_t)pLocalParams, FLASH_PAGE_SIZE-1);
|
||||
FLib_MemSet(pHwParams, 0xFF, sizeof(hardwareParameters_t));
|
||||
status = 1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (FLib_MemCmp(FREESCALE_PROD_DATA_BASE_ADDR, (void*)mProdDataIdentifier, sizeof(mProdDataIdentifier)) &&
|
||||
NV_VerifyCrcOverHWParameters(pLocalParams))
|
||||
{
|
||||
FLib_MemCpy(pHwParams, FREESCALE_PROD_DATA_BASE_ADDR, sizeof(hardwareParameters_t));
|
||||
status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FLib_MemSet(pHwParams, 0xFF, sizeof(hardwareParameters_t));
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Store the HW parameters to Flash
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return error code of the Flash erase/write functions
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_WriteHWParameters(hardwareParameters_t *pHwParams)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
NV_Init();
|
||||
|
||||
#ifndef CPU_JN518X
|
||||
#ifdef CPU_JN518X
|
||||
|
||||
status = FLASH_BlankCheck(FLASH, (uint8_t *)FREESCALE_PROD_DATA_BASE_ADDR,
|
||||
(uint8_t *)(FREESCALE_PROD_DATA_BASE_ADDR + sizeof(hardwareParameters_t)));
|
||||
#endif
|
||||
|
||||
if(
|
||||
#ifdef CPU_JN518X
|
||||
(status == kStatus_FLASH_Success) ||
|
||||
#endif
|
||||
!FLib_MemCmp(pHwParams, (void*)FREESCALE_PROD_DATA_BASE_ADDR, sizeof(hardwareParameters_t)))
|
||||
{
|
||||
pHwParams->hardwareParamsCrc = NV_ComputeCrcOverHWParameters(pHwParams);
|
||||
FLib_MemCpy(pHwParams->identificationWord, (void*)mProdDataIdentifier, sizeof(mProdDataIdentifier));
|
||||
|
||||
#if defined(FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE)
|
||||
status = NV_FlashEraseSector((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
#elif defined(FSL_FEATURE_FLASH_PAGE_SIZE_BYTES)
|
||||
status = NV_FlashEraseSector((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR, FSL_FEATURE_FLASH_PAGE_SIZE_BYTES);
|
||||
#endif
|
||||
|
||||
if( kStatus_FLASH_Success == status )
|
||||
{
|
||||
status = NV_FlashProgramUnaligned((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR,
|
||||
sizeof(hardwareParameters_t),
|
||||
(uint8_t*)pHwParams);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
#endif /* neither CPU_QN908X not CPU_JN518X */
|
||||
Vendored
Executable
+238
@@ -0,0 +1,238 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017, 2019 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef __FLASH_ADAPTER_H__
|
||||
#define __FLASH_ADAPTER_H__
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_flash.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*
|
||||
* Name: gNvDisableIntCmdSeq_c
|
||||
* Description: this macro is used to enable/disable interrupts when the
|
||||
* FTFL controller executes a command sequence. This macro
|
||||
* has to be set according to NVM configuration. Therefore,
|
||||
* if the FLASH region used by the NVM is placed in the same
|
||||
* program block as the ISR's executable code, the interrupts
|
||||
* MUST be disabled (because no code pre-fetching can be performed
|
||||
* while FTFL controller executes a command sequence, i.e.
|
||||
* program/erase). If the interrupts are not disabled, the
|
||||
* system will assert a hard fault when the flash controller
|
||||
* executes a command sequnce and an IRQ is about to be handled.
|
||||
* If the NVM region is placed in a different program block than
|
||||
* the ISR's code, this macro shall be set to FALSE (recommended).
|
||||
*/
|
||||
#ifndef gNvDisableIntCmdSeq_c
|
||||
#define gNvDisableIntCmdSeq_c (1)
|
||||
#endif
|
||||
|
||||
/* size of array to copy__Launch_Command function to.*/
|
||||
/* It should be at least equal to actual size of __Launch_Command func */
|
||||
/* User can change this value based on RAM size availability and actual size of __Launch_Command function */
|
||||
#define LAUNCH_CMD_SIZE 64
|
||||
#define PGM_SIZE_BYTE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE
|
||||
#define P_BLOCK_NUM FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT
|
||||
#define P_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
|
||||
/* Data Flash block information */
|
||||
#define FLEXNVM_BASE FSL_FEATURE_FLASH_FLEX_NVM_START_ADDRESS
|
||||
#define FLEXNVM_SECTOR_SIZE FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE
|
||||
#define FLEXNVM_BLOCK_SIZE FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SIZE
|
||||
#define FLEXNVM_BLOCK_NUM FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT
|
||||
/* Other defines */
|
||||
#define DEBUGENABLE 0x00
|
||||
#define FTFx_REG_BASE 0x40020000
|
||||
#define P_FLASH_BASE 0x00000000
|
||||
|
||||
/* Flex Ram block information */
|
||||
#define EERAM_BASE FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS
|
||||
#define EERAM_SIZE FSL_FEATURE_FLASH_FLEX_RAM_SIZE
|
||||
|
||||
#define READ_NORMAL_MARGIN 0x00
|
||||
#define READ_USER_MARGIN 0x01
|
||||
#define READ_FACTORY_MARGIN 0x02
|
||||
|
||||
|
||||
|
||||
#define NV_FlashRead(pSrc, pDest, size) FLib_MemCpy((void*)(pDest), (void*)(pSrc), size);
|
||||
|
||||
#if defined(CPU_QN908X)
|
||||
#define kStatus_FLASH_AlignmentError MAKE_STATUS(kStatusGroup_FLASH, 6)
|
||||
#elif defined(CPU_JN518X)
|
||||
|
||||
#define FLASH_AUDIT_DONE 0xc65c
|
||||
int PsectorUpdateFlashAudit(uint32_t new_value);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define PGM_SIZE_BYTE_LOG LOG(PGM_SIZE_BYTE)
|
||||
#define FLASH_PAGE_SZ_LOG LOG(FLASH_PAGE_SIZE)
|
||||
#define IS_MULTIPLE_OF_SECT_SIZE(len) (((len) & (FLASH_PAGE_SIZE-1)) == 0)
|
||||
#define SIZE2SEGNB(sz, sz_log) ((sz)>>(sz_log))
|
||||
#define ADDR2SEG(addr, sz_log) (((uint32_t)(addr))>>(sz_log))
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
extern uint32_t Image$$INT_STORAGE$$Base[];
|
||||
extern uint32_t Image$$INT_STORAGE$$Length[];
|
||||
extern uint32_t Image$$INT_STORAGE$$End[];
|
||||
|
||||
#define INT_STORAGE_START_OFFSET ((uint32_t)Image$$INT_STORAGE$$Base)
|
||||
#define INT_STORAGE_TOTAL_SIZE ((uint32_t)Image$$INT_STORAGE$$Length)
|
||||
#define INT_STORAGE_END_OFFSET ((uint32_t)Image$$INT_STORAGE$$End)
|
||||
|
||||
#else /* defined(__CC_ARM) */
|
||||
extern uint32_t INT_STORAGE_START[];
|
||||
extern uint32_t INT_STORAGE_SIZE[];
|
||||
extern uint32_t INT_STORAGE_END[];
|
||||
extern uint32_t INT_STORAGE_SECTOR_SIZE[];
|
||||
#define INT_STORAGE_START_OFFSET ((uint32_t)INT_STORAGE_END)
|
||||
#define INT_STORAGE_END_OFFSET ((uint32_t)INT_STORAGE_START)
|
||||
#define INT_STORAGE_TOTAL_SIZE ((uint32_t)INT_STORAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_END_ADDRESS
|
||||
* Description: NV_STORAGE_END_ADDRESS from linker command file is used by this code
|
||||
* as Raw Sector Start Address.
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_END_ADDRESS[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_SECTOR_SIZE
|
||||
* Description: external symbol from linker command file, it represents the size
|
||||
* of a FLASH sector
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_SECTOR_SIZE[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_MAX_SECTORS
|
||||
* Description: external symbol from linker command file, it represents the sectors
|
||||
* count used by the ENVM storage system; it has to be a multiple of 2
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_MAX_SECTORS[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_START_ADDRESS
|
||||
* Description: NV_STORAGE_START_ADDRESS from linker command file is used by this code
|
||||
* as Raw Sector End Address. Start is End address
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_START_ADDRESS[];
|
||||
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/* Flash address of the Product Data sector */
|
||||
#if defined(__CC_ARM)
|
||||
extern uint32_t Load$$LR$$LR_Prod_Data$$Base[];
|
||||
#define FREESCALE_PROD_DATA_BASE_ADDR Load$$LR$$LR_Prod_Data$$Base
|
||||
#else
|
||||
extern uint32_t FREESCALE_PROD_DATA_BASE_ADDR[];
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! GCC would warn about packing, so add pragma to repress warning */
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
typedef PACKED_STRUCT hardwareParameters_tag
|
||||
{
|
||||
uint8_t identificationWord[10]; /* valid data present */
|
||||
#ifdef CPU_JN518X
|
||||
uint8_t flash_audit_done;
|
||||
uint8_t reserved[3];
|
||||
#else
|
||||
uint8_t reserved[32]; /* for backward compatibillity */
|
||||
uint8_t ieee_802_15_4_address[8]; /* IEEE 802.15.4 MAC address */
|
||||
uint8_t bluetooth_address[6]; /* Bluetooth address */
|
||||
uint32_t xtalTrim; /* KW4x only */
|
||||
uint32_t edCalibrationOffset; /* KW01 ED offset */
|
||||
uint32_t pllFStepOffset; /* KW01 fine tune pll */
|
||||
#endif
|
||||
uint32_t gInternalStorageAddr; /* The start address of the internal storage used for OTA update.
|
||||
A value of 0xFFFFFFFF means that the External storage is used.
|
||||
Warning: The offset to this field in respect to the start address of the structure
|
||||
must not be changed.*/
|
||||
/* For forward compatibility additional fields may be added here
|
||||
Existing data in flash will not be compatible after modifying the hardwareParameters_t typedef*/
|
||||
uint16_t hardwareParamsCrc; /* crc for data between start of reserved area and start of hardwareParamsCrc field (not included). */
|
||||
}hardwareParameters_t;
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
extern flash_config_t gFlashConfig;
|
||||
|
||||
extern hardwareParameters_t gHardwareParameters;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void NV_Init(void);
|
||||
|
||||
uint32_t NV_FlashProgram( uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData);
|
||||
|
||||
uint32_t NV_FlashProgramUnaligned(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData);
|
||||
|
||||
uint32_t NV_FlashEraseSector(uint32_t dest,
|
||||
uint32_t size);
|
||||
|
||||
#if defined(CPU_JN518X)
|
||||
#define FLASH_ERASE_AREA(ADDR, SZ) FLASH_Erase(FLASH, (uint8_t *)(ADDR), (uint8_t *)((ADDR) + (SZ) - 1))
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(FLASH, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(FLASH)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) FLASH_BlankCheck(FLASH, (uint8_t *)(ADDR), (uint8_t *)((ADDR) + (SZ) - 1))
|
||||
#elif defined(CPU_QN908X)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) SwFlashVerifyErase((ADDR), (SZ), ,kFLASH_MarginValueNormal)
|
||||
#define FLASH_ERASE_AREA(ADDR, SZ) FLASH_Erase(&gFlashConfig, (ADDR), (SZ))
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(&gFlashConfig, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(&gFlashConfig)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) SwFlashVerifyErase ((ADDR), (SZ))
|
||||
#else
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) NV_FlashVerifyErase(ADDR, SZ)
|
||||
#define FLASH_ERASE_AREA, SZ) FLASH_Erase(&gFlashConfig, (ADDR), (SZ), kFLASH_ApiEraseKey)
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(&gFlashConfig, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(&gFlashConfig)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) FLASH_VerifyErase(&gFlashConfig, (ADDR), (SZ), kFLASH_MarginValueNormal)
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t NV_ReadHWParameters(hardwareParameters_t *pHwParams);
|
||||
|
||||
uint32_t NV_WriteHWParameters(hardwareParameters_t *pHwParams);
|
||||
|
||||
void NV_Flash_SetCriticalSection(void);
|
||||
void NV_Flash_ClearCriticalSection(void);
|
||||
|
||||
#endif /* __FLASH_ADAPTER_H__ */
|
||||
Vendored
Executable
+573
@@ -0,0 +1,573 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This module contains various common functions like copy and compare routines.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#include "FunctionLib.h"
|
||||
|
||||
#if gUseToolchainMemFunc_d
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if gFLib_CheckBufferOverflow_d
|
||||
#include "MemManager.h"
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies bytes from one buffer to another.
|
||||
* The buffers should not overlap.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post The source and destination buffers must not overlap.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpy (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
|
||||
#if gUseToolchainMemFunc_d
|
||||
memcpy(pDst, pSrc, cBytes);
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = ((uint8_t*)pDst)+1;
|
||||
pSrc = ((uint8_t*)pSrc)+1;
|
||||
cBytes--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies the specified number of bytes from the
|
||||
* source address to the destination address. No attempt is made
|
||||
* to handle overlapping copies to prevent loss of data.
|
||||
* The copying is optimized to avoid alignment problems, and attempts
|
||||
* to copy 32bit numbers optimally.
|
||||
*
|
||||
* \param[in] from_ptr Pointer to the source buffer.
|
||||
*
|
||||
* \param[in, out] to_ptr Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] number_of_bytes Number of bytes to copy (32 bit value).
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyAligned32bit (void* to_ptr,
|
||||
const void* from_ptr,
|
||||
register uint32_t number_of_bytes)
|
||||
{
|
||||
uint8_t* from8_ptr = (uint8_t*)from_ptr;
|
||||
uint8_t* to8_ptr = (uint8_t*)to_ptr;
|
||||
uint16_t* from16_ptr = (uint16_t*)from_ptr;
|
||||
uint16_t* to16_ptr = (uint16_t*)to_ptr;
|
||||
register uint32_t* from32_ptr = (uint32_t*)from_ptr;
|
||||
register uint32_t* to32_ptr = (uint32_t*)to_ptr;
|
||||
|
||||
register uint32_t loops;
|
||||
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(to_ptr, number_of_bytes);
|
||||
#endif
|
||||
|
||||
if (number_of_bytes > 3)
|
||||
{
|
||||
/* Try to align source on word */
|
||||
if ((uint32_t)from_ptr & 1)
|
||||
{
|
||||
from8_ptr = (uint8_t*)from_ptr;
|
||||
to8_ptr = (uint8_t*)to_ptr;
|
||||
|
||||
*to8_ptr++ = *from8_ptr++;
|
||||
|
||||
from_ptr = from8_ptr;
|
||||
to_ptr = to8_ptr;
|
||||
--number_of_bytes;
|
||||
}
|
||||
|
||||
/* Try to align source on longword */
|
||||
if ((uint32_t)from_ptr & 2)
|
||||
{
|
||||
from16_ptr = (uint16_t*)from_ptr;
|
||||
to16_ptr = (uint16_t*)to_ptr;
|
||||
|
||||
*to16_ptr++ = *from16_ptr++;
|
||||
|
||||
from_ptr = from16_ptr;
|
||||
to_ptr = to16_ptr;
|
||||
number_of_bytes -= 2;
|
||||
}
|
||||
|
||||
from32_ptr = (uint32_t*)from_ptr;
|
||||
to32_ptr = (uint32_t*)to_ptr;
|
||||
|
||||
for (loops = number_of_bytes >> 2; loops != 0; loops--)
|
||||
{
|
||||
*to32_ptr++ = *from32_ptr++;
|
||||
}
|
||||
|
||||
from_ptr = from32_ptr;
|
||||
to_ptr = to32_ptr;
|
||||
}
|
||||
|
||||
/* Copy all remaining bytes */
|
||||
if (number_of_bytes & 2)
|
||||
{
|
||||
from16_ptr = (uint16_t*)from_ptr;
|
||||
to16_ptr = (uint16_t*)to_ptr;
|
||||
|
||||
*to16_ptr++ = *from16_ptr++;
|
||||
|
||||
from_ptr = from16_ptr;
|
||||
to_ptr = to16_ptr;
|
||||
}
|
||||
|
||||
if (number_of_bytes & 1)
|
||||
{
|
||||
*(uint8_t*)to_ptr = *(uint8_t*)from_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes from one buffer to another. The buffers should not overlap.
|
||||
* The function can copy in either direction. If 'dir' is TRUE, then the function
|
||||
* works like FLib_MemCpy(). If FALSE, the function swaps the buffer pointers
|
||||
* before copying.
|
||||
*
|
||||
* \param[in, out] pBuf1 Pointer to the destination/source buffer.
|
||||
*
|
||||
* \param[in, out] pBuf2 Pointer to the source/destination buffer.
|
||||
*
|
||||
* \param[in] dir Direction to copy: pBuf2->pBuf1 if TRUE, pBuf1->pBuf2 if FALSE
|
||||
*
|
||||
* \param[in] n Number of bytes to copy.
|
||||
*
|
||||
* \post The source and destination buffers must not overlap.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyDir (void* pBuf1,
|
||||
void* pBuf2,
|
||||
bool_t dir,
|
||||
uint32_t n)
|
||||
{
|
||||
if (dir)
|
||||
{
|
||||
FLib_MemCpy (pBuf1, pBuf2, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLib_MemCpy (pBuf2, pBuf1, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief The byte at index i from the source buffer is copied to index ((n-1) - i)
|
||||
* in the destination buffer (and vice versa).
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyReverseOrder (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
if(cBytes)
|
||||
{
|
||||
pDst = (uint8_t*)pDst + (uint32_t)(cBytes-1);
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = (uint8_t*)pDst-1;
|
||||
pSrc = (uint8_t*)pSrc+1;
|
||||
cBytes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function compares two buffers.
|
||||
*
|
||||
* \param[in] pData1 First buffer to compare.
|
||||
*
|
||||
* \param[in] pData2 Second buffer to compare.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to compare.
|
||||
*
|
||||
* \return This function return TRUE if the buffers are equal and FALSE otherwise.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmp (const void* pData1, /* IN: First memory block to compare */
|
||||
const void* pData2, /* IN: Second memory block to compare */
|
||||
uint32_t cBytes /* IN: Number of bytes to compare. */
|
||||
)
|
||||
{
|
||||
bool_t status = TRUE;
|
||||
#if gUseToolchainMemFunc_d
|
||||
if( memcmp(pData1, pData2, cBytes) )
|
||||
{
|
||||
status = FALSE;
|
||||
}
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
if ( *((uint8_t *)pData1) != *((uint8_t *)pData2))
|
||||
{
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
pData2 = (uint8_t* )pData2+1;
|
||||
pData1 = (uint8_t* )pData1+1;
|
||||
cBytes--;
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function compares each octet of a given location to a value.
|
||||
*
|
||||
* \param [in] pAddr location to be compared
|
||||
*
|
||||
* \param [in] val reference value
|
||||
*
|
||||
* \param [in] len length of location to be compared
|
||||
*
|
||||
* \return This function return TRUE if all octests match and FALSE otherwise.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmpToVal
|
||||
(
|
||||
const void* pAddr,
|
||||
uint8_t val,
|
||||
uint32_t len
|
||||
)
|
||||
{
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
|
||||
if(((uint8_t *)pAddr)[len] != val)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function resets all bytes in a specified buffer to a set value.
|
||||
*
|
||||
* \param[in,out] pDst Address of the buffer to set.
|
||||
*
|
||||
* \param[in] value Set value.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to set in the buffer (maximum 255 bytes).
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemSet (void* pData,
|
||||
uint8_t value,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pData, cBytes);
|
||||
#endif
|
||||
#if gUseToolchainMemFunc_d
|
||||
memset(pData, value, cBytes);
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
((uint8_t* )pData)[--cBytes] = value;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a buffer,
|
||||
* possibly into the same overlapping memory as it is taken from
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemInPlaceCpy (void* pDst,
|
||||
void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
if (pDst != pSrc)
|
||||
{
|
||||
/* Do nothing if copying to same position */
|
||||
if (pDst < pSrc)
|
||||
{
|
||||
/* If dst is before src in memory copy forward */
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = ((uint8_t*)pDst)+1;
|
||||
pSrc = ((uint8_t*)pSrc)+1;
|
||||
cBytes--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If dst is after src in memory copy backward */
|
||||
while(cBytes)
|
||||
{
|
||||
cBytes--;
|
||||
((uint8_t* )pDst)[cBytes] = ((uint8_t* )pSrc)[cBytes];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 16bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val16 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy16Unaligned (void* pDst,
|
||||
uint16_t val16)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val16);
|
||||
*pData = (uint8_t)(val16 >> 8);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 32bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val32 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy32Unaligned (void* pDst,
|
||||
uint32_t val32)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val32);
|
||||
*pData++ = (uint8_t)(val32 >> 8);
|
||||
*pData++ = (uint8_t)(val32 >> 16);
|
||||
*pData++ = (uint8_t)(val32 >> 24);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 64bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val64 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy64Unaligned (void* pDst,
|
||||
uint64_t val64)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val64);
|
||||
*pData++ = (uint8_t)(val64 >> 8);
|
||||
*pData++ = (uint8_t)(val64 >> 16);
|
||||
*pData++ = (uint8_t)(val64 >> 24);
|
||||
*pData++ = (uint8_t)(val64 >> 32);
|
||||
*pData++ = (uint8_t)(val64 >> 40);
|
||||
*pData++ = (uint8_t)(val64 >> 48);
|
||||
*pData = (uint8_t)(val64 >> 56);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function adds an offset to a pointer.
|
||||
*
|
||||
* \param[in,out] pPtr Pointer to the pointer to add the offset to
|
||||
*
|
||||
* \param[in] offset Offset to add to the specified pointer.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_AddOffsetToPointer (void** pPtr,
|
||||
uint32_t offset)
|
||||
{
|
||||
(*pPtr) = ((uint8_t* )*pPtr) + offset;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the length of a NULL terminated string.
|
||||
*
|
||||
* \param[in] str A NULL terminated string
|
||||
*
|
||||
* \return the size of string in bytes
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t FLib_StrLen(const char *str)
|
||||
{
|
||||
#if gUseToolchainMemFunc_d
|
||||
return strlen(str);
|
||||
#else
|
||||
register uint32_t len=0;
|
||||
|
||||
while(*str != '\0')
|
||||
{
|
||||
str++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies bytes from FLASH to ram.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
bool_t raise_error = FALSE;
|
||||
|
||||
TRY
|
||||
{
|
||||
FLib_MemCpy(pDst, pSrc, cBytes);
|
||||
}
|
||||
CATCH (BUS_EXCEPTION)
|
||||
{
|
||||
raise_error = TRUE;
|
||||
}
|
||||
YRT;
|
||||
|
||||
return raise_error;
|
||||
}
|
||||
#else
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
FLib_MemCpy(pDst, pSrc, cBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
Executable
+320
@@ -0,0 +1,320 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the Function Lib module header file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _FUNCTION_LIB_H_
|
||||
#define _FUNCTION_LIB_H_
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef gUseToolchainMemFunc_d
|
||||
#define gUseToolchainMemFunc_d 0
|
||||
#endif
|
||||
|
||||
#ifndef gFLib_CheckBufferOverflow_d
|
||||
#define gFLib_CheckBufferOverflow_d 0
|
||||
#endif
|
||||
|
||||
#define FLib_MemSet16 FLib_MemSet
|
||||
|
||||
|
||||
extern jmp_buf *exception_buf;
|
||||
#define TRY do {jmp_buf exc_buf; \
|
||||
jmp_buf *old_buf = exception_buf; \
|
||||
exception_buf = &exc_buf; \
|
||||
switch (setjmp(exc_buf)) { case 0:
|
||||
|
||||
#define CATCH(x) break; case x:
|
||||
#define YRT } exception_buf = old_buf; } while(0)
|
||||
|
||||
typedef enum {
|
||||
BUS_EXCEPTION = 1,
|
||||
} EXCEPTION_ERROR_T;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy the content of one memory block to another. The amount of data to copy
|
||||
* must be specified in number of bytes.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpy (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
void FLib_MemCpyAligned32bit (void* to_ptr,
|
||||
const void* from_ptr,
|
||||
register uint32_t number_of_bytes);
|
||||
|
||||
void FLib_MemCpyDir (void* pBuf1,
|
||||
void* pBuf2,
|
||||
bool_t dir,
|
||||
uint32_t n);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes. The byte at index i from the source buffer is copied to index
|
||||
* ((n-1) - i) in the destination buffer (and vice versa).
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyReverseOrder (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare two memory blocks. The number of bytes to compare must be specified.
|
||||
* If the blocks are equal byte by byte, the function returns TRUE,
|
||||
* and FALSE otherwise.
|
||||
*
|
||||
* \param[in] pData1 First memory block to compare
|
||||
* \param[in] pData2 Second memory block to compare
|
||||
* \param[in] cBytes Number of bytes to compare
|
||||
*
|
||||
* \return TRUE if memory areas are equal. FALSE othwerwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmp (const void* pData1,
|
||||
const void* pData2,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare each byte of a memory block to a given value. The number of bytes to compare
|
||||
must be specified.
|
||||
* If all the bytes are equal to the given value, the function returns TRUE,
|
||||
* and FALSE otherwise.
|
||||
*
|
||||
* \param[in] pAddr Location to be compared
|
||||
* \param[in] val Reference value
|
||||
* \param[in] length Number of bytes to compare
|
||||
*
|
||||
* \return TRUE if all bytes match and FALSE otherwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmpToVal(const void* pAddr,
|
||||
uint8_t val,
|
||||
uint32_t len
|
||||
);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Reset bytes in a memory block to a certain value. The value, and the number
|
||||
* of bytes to be set, are supplied as arguments.
|
||||
*
|
||||
* \param[in] pData Pointer to memory block to reset
|
||||
* \param[in] value Value that memory block will be set to
|
||||
* \param[in] cBytes Number of bytes to set
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemSet (void* pData,
|
||||
uint8_t value,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes, possibly into the same overlapping memory as it is taken from
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemInPlaceCpy (void* pDst,
|
||||
void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 16bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val16 The 16-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy16Unaligned (void* pDst,
|
||||
uint16_t val16
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 32bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val32 The 32-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy32Unaligned (void* pDst,
|
||||
uint32_t val32
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 64bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val64 The 64-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy64Unaligned (void* pDst,
|
||||
uint64_t val64
|
||||
);
|
||||
|
||||
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Add an offset to a pointer.
|
||||
*
|
||||
* \param[out] pPtr Pointer to the pointer to be updated
|
||||
* \param[in] offset The offset(in bytes) to be added
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_AddOffsetToPointer (void** pPtr,
|
||||
uint32_t offset);
|
||||
|
||||
#define FLib_AddOffsetToPtr(pPtr,offset) FLib_AddOffsetToPointer((void**)(pPtr),(offset))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the length of a NULL terminated string.
|
||||
*
|
||||
* \param[in] str A NULL terminated string
|
||||
*
|
||||
* \return the size of string in bytes
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t FLib_StrLen(const char *str);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare two bytes.
|
||||
*
|
||||
* \param[in] pCmp1 pointer to the first 2-byte compare value
|
||||
* \param[in] pCmp2 pointer to the second 2-byte compare value
|
||||
*
|
||||
* \return TRUE if the two bytes are equal, and FALSE otherwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_Cmp2Bytes(pCmp1, pCmp2) ((((uint8_t *)(pCmp1))[0] == ((uint8_t *)(pCmp2))[0]) && \
|
||||
(((uint8_t *)(pCmp1))[1] == ((uint8_t *)(pCmp2))[1]))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Returns the maximum value of arguments a and b.
|
||||
*
|
||||
* \return The maximum value of arguments a and b
|
||||
*
|
||||
* \remarks
|
||||
* The primitive should must be implemented as a macro, as it should be possible to
|
||||
* evaluate the result on compile time if the arguments are constants.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_GetMax(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Returns the minimum value of arguments a and b.
|
||||
*
|
||||
* \return The minimum value of arguments a and b
|
||||
*
|
||||
* \remarks
|
||||
* The primitive should must be implemented as a macro, as it should be possible to
|
||||
* evaluate the result on compile time if the arguments are constants.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_GetMin(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _CLZ(x) __builtin_clz(x)
|
||||
#endif
|
||||
#if defined (__IAR_SYSTEMS_ICC__)
|
||||
#define _CLZ(x) __CLZ(x)
|
||||
#endif
|
||||
#define _BSR(x) (31 - _CLZ(x))
|
||||
|
||||
static inline uint32_t Flib_Log2(uint32_t x)
|
||||
{
|
||||
uint32_t msb = _BSR(x);
|
||||
/* if not a power of 2, round to next so that x remains <= (1<<msb) */
|
||||
if (x > (1<< msb)) msb++;
|
||||
return msb;
|
||||
}
|
||||
|
||||
|
||||
#define LOG_1(n) (((n) >= 2) ? 1 : 0)
|
||||
#define LOG_2(n) (((n) >= 1<<2) ? (2 + LOG_1((n)>>2)) : LOG_1(n))
|
||||
#define LOG_4(n) (((n) >= 1<<4) ? (4 + LOG_2((n)>>4)) : LOG_2(n))
|
||||
#define LOG_8(n) (((n) >= 1<<8) ? (8 + LOG_4((n)>>8)) : LOG_4(n))
|
||||
#define LOG(n) (((n) >= 1<<16) ? (16 + LOG_8((n)>>16)) : LOG_8(n))
|
||||
|
||||
|
||||
|
||||
|
||||
#define MASK_LOG(log) ((1<<(log))-1)
|
||||
#define ROUND_FLOOR(x, log) (((x) >> (log)) << (log))
|
||||
#define ROUND_CEIL(x, log) ((((x) + MASK_LOG(log) ) >> (log)) << (log))
|
||||
#define IS_POW_OF_TWO(x) (((x) & ((x)-1)) == 0)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FUNCTION_LIB_H_ */
|
||||
+561
@@ -0,0 +1,561 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the linked lists part of the Utils package.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "GenericList.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! *********************************************************************************
|
||||
* \brief Initialises the list descriptor.
|
||||
*
|
||||
* \param[in] list - List handle to init.
|
||||
* max - Maximum number of elements in list. 0 for unlimited.
|
||||
*
|
||||
* \return void.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void ListInit(listHandle_t list, uint32_t max)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->max = max;
|
||||
list->size = 0;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the list that contains the given element.
|
||||
*
|
||||
* \param[in] element - Handle of the element.
|
||||
*
|
||||
* \return NULL if element is orphan.
|
||||
* Handle of the list the element is inserted into.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listHandle_t ListGetList(listElementHandle_t element)
|
||||
{
|
||||
return element->list;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links element to the tail of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to insert into.
|
||||
* element - element to add
|
||||
*
|
||||
* \return gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddTail(listHandle_t list, listElementHandle_t element)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (list->max != 0) && (list->max == list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->head = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail->next = element;
|
||||
}
|
||||
element->prev = list->tail;
|
||||
element->next = NULL;
|
||||
element->list = list;
|
||||
list->tail = element;
|
||||
list->size++;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links element to the head of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to insert into.
|
||||
* element - element to add
|
||||
*
|
||||
* \return gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddHead(listHandle_t list, listElementHandle_t element)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (list->max != 0) && (list->max == list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->tail = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head->prev = element;
|
||||
}
|
||||
element->next = list->head;
|
||||
element->prev = NULL;
|
||||
element->list = list;
|
||||
list->head = element;
|
||||
list->size++;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Unlinks element from the head of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to remove from.
|
||||
*
|
||||
* \return NULL if list is empty.
|
||||
* ID of removed element(pointer) if removal was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListRemoveHead(listHandle_t list)
|
||||
{
|
||||
listElementHandle_t element;
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if((NULL == list) || (list->size == 0))
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return NULL; /*List is empty*/
|
||||
}
|
||||
|
||||
element = list->head;
|
||||
list->size--;
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->tail = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
element->next->prev = NULL;
|
||||
}
|
||||
list->head = element->next; /*Is NULL if element is head*/
|
||||
element->list = NULL;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return element;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets head element ID.
|
||||
*
|
||||
* \param[in] list - ID of list.
|
||||
*
|
||||
* \return NULL if list is empty.
|
||||
* ID of head element if list is not empty.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetHead(listHandle_t list)
|
||||
{
|
||||
return list->head;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets next element ID.
|
||||
*
|
||||
* \param[in] element - ID of the element.
|
||||
*
|
||||
* \return NULL if element is tail.
|
||||
* ID of next element if exists.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetNext(listElementHandle_t element)
|
||||
{
|
||||
return element->next;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets previous element ID.
|
||||
*
|
||||
* \param[in] element - ID of the element.
|
||||
*
|
||||
* \return NULL if element is head.
|
||||
* ID of previous element if exists.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetPrev(listElementHandle_t element)
|
||||
{
|
||||
return element->prev;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Unlinks an element from its list.
|
||||
*
|
||||
* \param[in] element - ID of the element to remove.
|
||||
*
|
||||
* \return gOrphanElement_c if element is not part of any list.
|
||||
* gListOk_c if removal was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListRemoveElement(listElementHandle_t element)
|
||||
{
|
||||
if(element->list == NULL)
|
||||
{
|
||||
return gOrphanElement_c; /*Element was previusly removed or never added*/
|
||||
}
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if(element->prev == NULL) /*Element is head or solo*/
|
||||
{
|
||||
element->list->head = element->next; /*is null if solo*/
|
||||
}
|
||||
if(element->next == NULL) /*Element is tail or solo*/
|
||||
{
|
||||
element->list->tail = element->prev; /*is null if solo*/
|
||||
}
|
||||
if(element->prev != NULL) /*Element is not head*/
|
||||
{
|
||||
element->prev->next = element->next;
|
||||
}
|
||||
if(element->next != NULL) /*Element is not tail*/
|
||||
{
|
||||
element->next->prev = element->prev;
|
||||
}
|
||||
element->list->size--;
|
||||
element->list = NULL;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links an element in the previous position relative to a given member
|
||||
* of a list.
|
||||
*
|
||||
* \param[in] element - ID of a member of a list.
|
||||
* newElement - new element to insert before the given member.
|
||||
*
|
||||
* \return gOrphanElement_c if element is not part of any list.
|
||||
* gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddPrevElement(listElementHandle_t element, listElementHandle_t newElement)
|
||||
{
|
||||
if(element->list == NULL)
|
||||
{
|
||||
return gOrphanElement_c; /*Element was previusly removed or never added*/
|
||||
}
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (element->list->max != 0) && (element->list->max == element->list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(element->prev == NULL) /*Element is list head*/
|
||||
{
|
||||
element->list->head = newElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
element->prev->next = newElement;
|
||||
}
|
||||
newElement->list = element->list;
|
||||
element->list->size++;
|
||||
newElement->next = element;
|
||||
newElement->prev = element->prev;
|
||||
element->prev = newElement;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the current size of a list.
|
||||
*
|
||||
* \param[in] list - ID of the list.
|
||||
*
|
||||
* \return Current size of the list.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t ListGetSize(listHandle_t list)
|
||||
{
|
||||
return list->size;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the number of free places in the list.
|
||||
*
|
||||
* \param[in] list - ID of the list.
|
||||
*
|
||||
* \return Available size of the list.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t ListGetAvailable(listHandle_t list)
|
||||
{
|
||||
return (list->max - list->size);
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Creates, tests and deletes a list. Any error that occurs will trap the
|
||||
* CPU in a while(1) loop.
|
||||
*
|
||||
* \param[in] void.
|
||||
*
|
||||
* \return gListOk_c.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
/* To be removed or rewritten to remove MemManager dependency. */
|
||||
#if 0
|
||||
listStatus_t ListTest()
|
||||
{
|
||||
listHandle_t list;
|
||||
listElementHandle_t element, newElement;
|
||||
uint32_t i,freeBlocks;
|
||||
const uint32_t max = 10;
|
||||
|
||||
freeBlocks = MEM_GetAvailableFwkBlocks(0);
|
||||
/*create list*/
|
||||
list = ListCreate(max);
|
||||
LIST_ASSERT(list != NULL);
|
||||
|
||||
/*add elements*/
|
||||
for(i=0; i<max; i++)
|
||||
{
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListAddHead(list, element) == gListOk_c);
|
||||
LIST_ASSERT(list->head == element)
|
||||
ListRemoveHead(list);
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListOk_c);
|
||||
LIST_ASSERT(list->tail == element);
|
||||
if(ListGetSize(list) == 1)
|
||||
{
|
||||
LIST_ASSERT(list->head == element);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_ASSERT(list->head != element);
|
||||
}
|
||||
}
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
|
||||
/*add one more element*/
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListFull_c);
|
||||
list->max = 0;
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListOk_c);
|
||||
LIST_ASSERT(ListGetSize(list) == max+1);
|
||||
/*remove the extra element*/
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
LIST_ASSERT(MEM_BufferFree(element) == MEM_SUCCESS_c);
|
||||
list->max = max;
|
||||
|
||||
/*parse elements*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListGetNext(element);
|
||||
LIST_ASSERT(element != NULL);
|
||||
}
|
||||
LIST_ASSERT(element == list->tail);
|
||||
LIST_ASSERT(ListGetNext(element) == NULL);
|
||||
|
||||
/*Reverse parse elements*/
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListGetPrev(element);
|
||||
LIST_ASSERT(element != NULL);
|
||||
}
|
||||
LIST_ASSERT(element == list->head);
|
||||
LIST_ASSERT(ListGetPrev(element) == NULL);
|
||||
|
||||
/*Add prev*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListFull_c);
|
||||
LIST_ASSERT(ListGetHead(list) == element);
|
||||
list->max = 0;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(ListGetHead(list) == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = list->head->next->next;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(list->head->next->next == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = list->tail;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(list->tail->prev == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
element->list = NULL;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gOrphanElement_c);
|
||||
MEM_BufferFree(newElement);
|
||||
MEM_BufferFree(element);
|
||||
LIST_ASSERT(ListGetSize(list) == max+3);
|
||||
|
||||
/*Remove element*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element == list->head);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->head != element);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gOrphanElement_c);
|
||||
MEM_BufferFree(element);
|
||||
element = ListGetHead(list)->next->next;
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
MEM_BufferFree(element);
|
||||
element = list->tail;
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->tail != element);
|
||||
MEM_BufferFree(element);
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
list->max = max;
|
||||
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
MEM_BufferFree(element);
|
||||
}
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->head == NULL);
|
||||
LIST_ASSERT(list->tail == NULL);
|
||||
LIST_ASSERT(element->list == NULL);
|
||||
MEM_BufferFree(element);
|
||||
|
||||
/*List is empty here.*/
|
||||
LIST_ASSERT(ListGetSize(list) == 0);
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element == NULL);
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element == NULL);
|
||||
|
||||
MEM_BufferFree(list);
|
||||
/*Did we produce a memory leak?*/
|
||||
LIST_ASSERT(freeBlocks == MEM_GetAvailableFwkBlocks(0));
|
||||
|
||||
return gListOk_c;
|
||||
}
|
||||
#else
|
||||
listStatus_t ListTest(void)
|
||||
{
|
||||
return gListOk_c;
|
||||
}
|
||||
#endif
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the linked lists part of the Utils package.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _GENERIC_LIST_H_
|
||||
#define _GENERIC_LIST_H_
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macro definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
typedef enum
|
||||
{
|
||||
gListOk_c = 0,
|
||||
gListFull_c,
|
||||
gListEmpty_c,
|
||||
gOrphanElement_c
|
||||
}listStatus_t;
|
||||
|
||||
typedef struct list_tag
|
||||
{
|
||||
struct listElement_tag *head;
|
||||
struct listElement_tag *tail;
|
||||
uint16_t size;
|
||||
uint16_t max;
|
||||
}list_t, *listHandle_t;
|
||||
|
||||
typedef struct listElement_tag
|
||||
{
|
||||
struct listElement_tag *next;
|
||||
struct listElement_tag *prev;
|
||||
struct list_tag *list;
|
||||
}listElement_t, *listElementHandle_t;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void ListInit(listHandle_t list, uint32_t max);
|
||||
listHandle_t ListGetList(listElementHandle_t element);
|
||||
listStatus_t ListAddHead(listHandle_t list, listElementHandle_t element);
|
||||
listStatus_t ListAddTail(listHandle_t list, listElementHandle_t element);
|
||||
listElementHandle_t ListRemoveHead(listHandle_t list);
|
||||
listElementHandle_t ListGetHead(listHandle_t list);
|
||||
listElementHandle_t ListGetNext(listElementHandle_t element);
|
||||
listElementHandle_t ListGetPrev(listElementHandle_t element);
|
||||
listStatus_t ListRemoveElement(listElementHandle_t element);
|
||||
listStatus_t ListAddPrevElement(listElementHandle_t element, listElementHandle_t newElement);
|
||||
uint32_t ListGetSize(listHandle_t list);
|
||||
uint32_t ListGetAvailable(listHandle_t list);
|
||||
listStatus_t ListTest(void);
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifdef DEBUG_ASSERT
|
||||
#define LIST_ASSERT(condition) if(!(condition))while(1);
|
||||
#else
|
||||
#define LIST_ASSERT(condition) (void)(condition);
|
||||
#endif
|
||||
|
||||
#endif /*_GENERIC_LIST_H_*/
|
||||
Vendored
Executable
+223
@@ -0,0 +1,223 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the Memory Manager interface.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _MEM_MANAGER_H_
|
||||
#define _MEM_MANAGER_H_
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include <stddef.h>
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "GenericList.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Defines pools by block size and number of blocks. Must be alligned to 4 bytes.*/
|
||||
#ifndef PoolsDetails_c
|
||||
#define PoolsDetails_c \
|
||||
_block_size_ 64 _number_of_blocks_ 8 _pool_id_(0) _eol_ \
|
||||
_block_size_ 128 _number_of_blocks_ 2 _pool_id_(0) _eol_ \
|
||||
_block_size_ 256 _number_of_blocks_ 6 _pool_id_(0) _eol_
|
||||
#endif
|
||||
|
||||
#if defined (__IAR_SYSTEMS_ICC__)
|
||||
/* __get_LR() declaration not included to avoid issues with different versions of IAR compiler */
|
||||
#elif defined(__GNUC__)
|
||||
#define __get_LR() __builtin_return_address(0)
|
||||
#elif defined(__CC_ARM)
|
||||
#define __get_LR() __return_address()
|
||||
#endif
|
||||
|
||||
/* If a buffer (that is not allocated forever using MEM_BufferAllocForever()) is not freed
|
||||
in MEM_CheckMemBufferThreshold_c ms, the device will enter into panic */
|
||||
#ifndef MEM_CheckMemBufferThreshold_c
|
||||
#define MEM_CheckMemBufferThreshold_c 120000 /* ms */
|
||||
#endif
|
||||
|
||||
/* How often the device should check if the above threshold expired */
|
||||
#ifndef MEM_CheckMemBufferInterval_c
|
||||
#define MEM_CheckMemBufferInterval_c 15000 /* ms */
|
||||
#endif
|
||||
|
||||
/* Default memory allocator */
|
||||
#ifndef MEM_BufferAlloc
|
||||
#define MEM_BufferAlloc(numBytes) MEM_BufferAllocWithId(numBytes, 0, (void*)__get_LR())
|
||||
#endif
|
||||
|
||||
/* Allocate a block from the memory pools forever.*/
|
||||
#define MEM_BufferAllocForever(numBytes,poolId) MEM_BufferAllocWithId(numBytes, poolId, (void*)((uintptr_t)__get_LR() | 0x80000000 ))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Defines statuses used in MEM_BufferAlloc and MEM_BufferFree*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_SUCCESS_c = 0, /* No error occurred */
|
||||
MEM_INIT_ERROR_c, /* Memory initialization error */
|
||||
MEM_ALLOC_ERROR_c, /* Memory allocation error */
|
||||
MEM_FREE_ERROR_c, /* Memory free error */
|
||||
MEM_UNKNOWN_ERROR_c /* something bad has happened... */
|
||||
}memStatus_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Initialises the Memory Manager.*/
|
||||
memStatus_t MEM_Init(void);
|
||||
/*Returns the number of available blocks that fit the given size.*/
|
||||
uint32_t MEM_GetAvailableBlocks(uint32_t size);
|
||||
/*Frees the givem buffer.*/
|
||||
memStatus_t MEM_BufferFree(void* buffer);
|
||||
/*Returns the allocated buffer of the given size.*/
|
||||
void* MEM_BufferAllocWithId(uint32_t numBytes , uint8_t poolId, void *pCaller);
|
||||
/*Returns the size of a given buffer*/
|
||||
uint16_t MEM_BufferGetSize(void* buffer);
|
||||
/*Performs a write-read-verify test accross all pools*/
|
||||
uint32_t MEM_WriteReadTest(void);
|
||||
#if (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX))
|
||||
/*Free a buffer on the Master core*/
|
||||
memStatus_t MEM_BufferFreeOnMaster(uint8_t * pBuff);
|
||||
/*Free a buffer on the Slave core*/
|
||||
memStatus_t MEM_BufferFreeOnSlave(uint8_t * pBuff);
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if defined(MEM_TRACKING) && defined(DEBUG_ASSERT)
|
||||
#define MEM_ASSERT(condition) if(!(condition))while(1);
|
||||
#else
|
||||
#define MEM_ASSERT(condition) (void)(condition);
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
/*Statistics structure definition. Used by pools.*/
|
||||
typedef struct poolStat_tag
|
||||
{
|
||||
uint16_t numBlocks;
|
||||
uint16_t allocatedBlocks;
|
||||
uint16_t allocatedBlocksPeak;
|
||||
uint16_t allocationFailures;
|
||||
uint16_t freeFailures;
|
||||
#ifdef MEM_TRACKING
|
||||
uint16_t poolFragmentWaste;
|
||||
uint16_t poolFragmentWastePeak;
|
||||
uint16_t poolFragmentMinWaste;
|
||||
uint16_t poolFragmentMaxWaste;
|
||||
#endif /*MEM_TRACKING*/
|
||||
} poolStat_t;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
/*Definition for alloc indicators. Used in buffer tracking.*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_TRACKING_FREE_c = 0,
|
||||
MEM_TRACKING_ALLOC_c,
|
||||
}memTrackingStatus_t;
|
||||
|
||||
/*Tracking structure definition.*/
|
||||
typedef PACKED_STRUCT BlockTracking_tag
|
||||
{
|
||||
void *blockAddr; /*Addr of Msg, not that this pointer is
|
||||
4 byte bigger than the addr in the pool
|
||||
has the header of the msg is 4 bytes */
|
||||
uint16_t blockSize; /*Size of block in bytes.*/
|
||||
uint16_t fragmentWaste; /*Size requested by allocator.*/
|
||||
void *allocAddr; /*Return address of last Alloc made */
|
||||
void *freeAddr; /*Return address of last Free made */
|
||||
uint16_t allocCounter; /*No of time this msg has been allocated */
|
||||
uint16_t freeCounter; /*No of time this msg has been freed */
|
||||
memTrackingStatus_t allocStatus; /*1 if currently allocated, 0 if currently free */
|
||||
uint32_t timeStamp;
|
||||
void *pCaller;
|
||||
}blockTracking_t;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/*Header description for buffers.*/
|
||||
typedef struct listHeader_tag
|
||||
{
|
||||
listElement_t link;
|
||||
struct pools_tag *pParentPool;
|
||||
}listHeader_t;
|
||||
|
||||
/*Buffer pools. Used by most functions*/
|
||||
typedef struct pools_tag
|
||||
{
|
||||
list_t anchor; /* MUST be first element in pools_t struct */
|
||||
uint16_t nextBlockSize;
|
||||
uint16_t blockSize;
|
||||
uint16_t poolId;
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStat_t poolStatistics;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
uint8_t numBlocks;
|
||||
uint8_t allocatedBlocks;
|
||||
}pools_t;
|
||||
|
||||
/*Buffer pool description. Used by MM_Init() for creating the buffer pools. */
|
||||
typedef struct poolInfo_tag
|
||||
{
|
||||
uint16_t blockSize;
|
||||
uint16_t poolSize;
|
||||
uint16_t poolId;
|
||||
uint8_t padding[2];
|
||||
}poolInfo_t;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize, void *pCaller);
|
||||
uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size);
|
||||
void MEM_CheckIfMemBuffersAreFreed(void);
|
||||
|
||||
/* The timestamp function used by MEM Manager for debug purpose.
|
||||
The timestamp must be in milliseconds! */
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
extern __weak uint32_t MEM_GetTimeStamp(void);
|
||||
#elif defined(__GNUC__)
|
||||
extern __attribute__((weak)) uint32_t MEM_GetTimeStamp(void);
|
||||
#endif
|
||||
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
#endif /* _MEM_MANAGER_H_ */
|
||||
Vendored
Executable
+815
@@ -0,0 +1,815 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the Memory Manager.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#include "Panic.h"
|
||||
#include "MemManager.h"
|
||||
#include "FunctionLib.h"
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#define _block_size_ {
|
||||
#define _number_of_blocks_ ,
|
||||
#define _pool_id_(a) , a ,
|
||||
#define _eol_ },
|
||||
|
||||
|
||||
poolInfo_t poolInfo[] =
|
||||
{
|
||||
PoolsDetails_c
|
||||
{0, 0, 0} /*termination tag*/
|
||||
};
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#define _block_size_ (sizeof(listHeader_t)+
|
||||
#define _number_of_blocks_ ) *
|
||||
#define _eol_ +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define heapSize_c (PoolsDetails_c 0)
|
||||
|
||||
/* Heap */
|
||||
uint32_t memHeap[heapSize_c/sizeof(uint32_t)];
|
||||
const uint32_t heapSize = heapSize_c;
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#define _block_size_ 0 *
|
||||
#define _number_of_blocks_ + 0 *
|
||||
#define _eol_ + 1 +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define poolCount (PoolsDetails_c 0)
|
||||
|
||||
/* Memory pool info and anchors. */
|
||||
pools_t memPools[poolCount];
|
||||
#ifdef MEM_STATISTICS
|
||||
pools_t memPoolsSnapShot[poolCount];
|
||||
#endif
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
|
||||
#ifndef NUM_OF_TRACK_PTR
|
||||
#define NUM_OF_TRACK_PTR 1
|
||||
#endif
|
||||
|
||||
#define _block_size_ 0*
|
||||
#define _number_of_blocks_ +
|
||||
#define _eol_ +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define mTotalNoOfMsgs_d (PoolsDetails_c 0)
|
||||
static const uint16_t mTotalNoOfMsgs_c = mTotalNoOfMsgs_d;
|
||||
blockTracking_t memTrack[mTotalNoOfMsgs_d];
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/* Free messages counter. Not used by module. */
|
||||
uint16_t gFreeMessagesCount;
|
||||
#ifdef MEM_STATISTICS
|
||||
uint16_t gFreeMessagesCountMin = 0xFFFF;
|
||||
uint16_t gTotalFragmentWaste = 0;
|
||||
uint16_t gMaxTotalFragmentWaste = 0;
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function initializes the message module private variables.
|
||||
* Must be called at boot time, or if device is reset.
|
||||
*
|
||||
* \param[in] none
|
||||
*
|
||||
* \return MEM_SUCCESS_c if initialization is successful. (It's always successful).
|
||||
*
|
||||
********************************************************************************** */
|
||||
memStatus_t MEM_Init(void)
|
||||
{
|
||||
poolInfo_t *pPoolInfo = poolInfo; /* IN: Memory layout information */
|
||||
pools_t *pPools = memPools;/* OUT: Will be initialized with requested memory pools. */
|
||||
uint8_t *pHeap = (uint8_t *)memHeap;/* IN: Memory heap.*/
|
||||
|
||||
uint16_t poolN;
|
||||
#ifdef MEM_TRACKING
|
||||
uint16_t memTrackIndex = 0;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
gFreeMessagesCount = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
poolN = pPoolInfo->poolSize;
|
||||
ListInit((listHandle_t)&pPools->anchor, poolN);
|
||||
#ifdef MEM_STATISTICS
|
||||
pPools->poolStatistics.numBlocks = 0;
|
||||
pPools->poolStatistics.allocatedBlocks = 0;
|
||||
pPools->poolStatistics.allocatedBlocksPeak = 0;
|
||||
pPools->poolStatistics.allocationFailures = 0;
|
||||
pPools->poolStatistics.freeFailures = 0;
|
||||
#ifdef MEM_TRACKING
|
||||
pPools->poolStatistics.poolFragmentWaste = 0;
|
||||
pPools->poolStatistics.poolFragmentWastePeak = 0;
|
||||
pPools->poolStatistics.poolFragmentMinWaste = 0xFFFF;
|
||||
pPools->poolStatistics.poolFragmentMaxWaste = 0;
|
||||
#endif /*MEM_TRACKING*/
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
while(poolN)
|
||||
{
|
||||
/* Add block to list of free memory. */
|
||||
ListAddTail((listHandle_t)&pPools->anchor, (listElementHandle_t)&((listHeader_t *)pHeap)->link);
|
||||
((listHeader_t *)pHeap)->pParentPool = pPools;
|
||||
#ifdef MEM_STATISTICS
|
||||
pPools->poolStatistics.numBlocks++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
pPools->numBlocks++;
|
||||
gFreeMessagesCount++;
|
||||
#ifdef MEM_TRACKING
|
||||
memTrack[memTrackIndex].blockAddr = (void *)(pHeap + sizeof(listHeader_t));
|
||||
memTrack[memTrackIndex].blockSize = pPoolInfo->blockSize;
|
||||
memTrack[memTrackIndex].fragmentWaste = 0;
|
||||
memTrack[memTrackIndex].allocAddr = NULL;
|
||||
memTrack[memTrackIndex].allocCounter = 0;
|
||||
memTrack[memTrackIndex].allocStatus = MEM_TRACKING_FREE_c;
|
||||
memTrack[memTrackIndex].freeAddr = NULL;
|
||||
memTrack[memTrackIndex].freeCounter = 0;
|
||||
memTrackIndex++;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/* Add block size (without list header)*/
|
||||
pHeap += pPoolInfo->blockSize + sizeof(listHeader_t);
|
||||
poolN--;
|
||||
}
|
||||
|
||||
pPools->blockSize = pPoolInfo->blockSize;
|
||||
pPools->poolId = pPoolInfo->poolId;
|
||||
pPools->nextBlockSize = (pPoolInfo+1)->blockSize;
|
||||
if(pPools->nextBlockSize == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pPools++;
|
||||
pPoolInfo++;
|
||||
}
|
||||
|
||||
return MEM_SUCCESS_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the number of available blocks greater or
|
||||
* equal to the given size.
|
||||
*
|
||||
* \param[in] size - Size of blocks to check for availability.
|
||||
*
|
||||
* \return Number of available blocks greater or equal to the given size.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t MEM_GetAvailableBlocks
|
||||
(
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
pools_t *pPools = memPools;
|
||||
uint32_t pTotalCount = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(size <= pPools->blockSize)
|
||||
{
|
||||
pTotalCount += ListGetSize((listHandle_t)&pPools->anchor);
|
||||
}
|
||||
|
||||
if(pPools->nextBlockSize == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pPools++;
|
||||
}
|
||||
|
||||
return pTotalCount;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Allocate a block from the memory pools. The function uses the
|
||||
* numBytes argument to look up a pool with adequate block sizes.
|
||||
* \param[in] numBytes - Size of buffer to allocate.
|
||||
*
|
||||
* \return Pointer to the allocated buffer, NULL if failed.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Allocate a block from the memory pools. The function uses the
|
||||
* numBytes argument to look up a pool with adequate block sizes.
|
||||
* \param[in] numBytes - Size of buffer to allocate.
|
||||
* \param[in] poolId - The ID of the pool where to search for a free buffer.
|
||||
* \param[in] pCaller - pointer to the caller function (Debug purpose)
|
||||
*
|
||||
* \return Pointer to the allocated buffer, NULL if failed.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void* MEM_BufferAllocWithId
|
||||
(
|
||||
uint32_t numBytes,
|
||||
uint8_t poolId,
|
||||
void *pCaller
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif
|
||||
#if defined(MEM_TRACKING) || defined(MEM_DEBUG_OUT_OF_MEMORY)
|
||||
uint16_t requestedSize = numBytes;
|
||||
#endif /*MEM_TRACKING*/
|
||||
#ifdef MEM_STATISTICS
|
||||
bool_t allocFailure = FALSE;
|
||||
#endif
|
||||
|
||||
pools_t *pPools = memPools;
|
||||
listHeader_t *pBlock;
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
while(numBytes)
|
||||
{
|
||||
if( (numBytes <= pPools->blockSize) && (poolId == pPools->poolId) )
|
||||
{
|
||||
pBlock = (listHeader_t *)ListRemoveHead((listHandle_t)&pPools->anchor);
|
||||
|
||||
if(NULL != pBlock)
|
||||
{
|
||||
pBlock++;
|
||||
gFreeMessagesCount--;
|
||||
pPools->allocatedBlocks++;
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
if(gFreeMessagesCount < gFreeMessagesCountMin)
|
||||
{
|
||||
gFreeMessagesCountMin = gFreeMessagesCount;
|
||||
}
|
||||
|
||||
pPools->poolStatistics.allocatedBlocks++;
|
||||
if ( pPools->poolStatistics.allocatedBlocks > pPools->poolStatistics.allocatedBlocksPeak )
|
||||
{
|
||||
pPools->poolStatistics.allocatedBlocksPeak = pPools->poolStatistics.allocatedBlocks;
|
||||
}
|
||||
MEM_ASSERT(pPools->poolStatistics.allocatedBlocks <= pPools->poolStatistics.numBlocks);
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
MEM_Track(pBlock, MEM_TRACKING_ALLOC_c, savedLR, requestedSize, pCaller);
|
||||
#endif /*MEM_TRACKING*/
|
||||
OSA_InterruptEnable();
|
||||
return pBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MEM_STATISTICS
|
||||
if(!allocFailure)
|
||||
{
|
||||
pPools->poolStatistics.allocationFailures++;
|
||||
allocFailure = TRUE;
|
||||
}
|
||||
#endif /*MEM_STATISTICS*/
|
||||
if(numBytes > pPools->nextBlockSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* No more blocks of that size, try next size. */
|
||||
numBytes = pPools->nextBlockSize;
|
||||
}
|
||||
}
|
||||
/* Try next pool*/
|
||||
if(pPools->nextBlockSize)
|
||||
{
|
||||
pPools++;
|
||||
}
|
||||
else
|
||||
{
|
||||
numBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEM_DEBUG_OUT_OF_MEMORY
|
||||
if (requestedSize)
|
||||
{
|
||||
panic( 0, (uint32_t)MEM_BufferAllocWithId, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Deallocate a memory block by putting it in the corresponding pool
|
||||
* of free blocks.
|
||||
*
|
||||
* \param[in] buffer - Pointer to buffer to deallocate.
|
||||
*
|
||||
* \return MEM_SUCCESS_c if deallocation was successful, MEM_FREE_ERROR_c if not.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
* \remarks Never deallocate the same buffer twice.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#if (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX))
|
||||
#if defined MULTICORE_HOST
|
||||
memStatus_t MEM_BufferFreeOnMaster
|
||||
#elif defined MULTICORE_BLACKBOX
|
||||
memStatus_t MEM_BufferFreeOnSlave
|
||||
#endif /* MULTICORE_HOST */
|
||||
(
|
||||
uint8_t *pBuff
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif /*MEM_TRACKING*/
|
||||
listHeader_t *pHeader;
|
||||
|
||||
if( pBuff == NULL )
|
||||
{
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
pHeader = (listHeader_t *)pBuff-1;
|
||||
|
||||
if( ((uint8_t*)pHeader < (uint8_t*)memHeap) || ((uint8_t*)pHeader > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MEM_BufferFree(pBuff);
|
||||
}
|
||||
}
|
||||
#endif /* (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX)) */
|
||||
|
||||
memStatus_t MEM_BufferFree
|
||||
(
|
||||
void* buffer /* IN: Block of memory to free*/
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif /*MEM_TRACKING*/
|
||||
listHeader_t *pHeader;
|
||||
pools_t *pParentPool;
|
||||
pools_t *pool;
|
||||
|
||||
if( buffer == NULL )
|
||||
{
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
pHeader = (listHeader_t *)buffer-1;
|
||||
|
||||
if( ((uint8_t*)pHeader < (uint8_t*)memHeap) || ((uint8_t*)pHeader > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
#if (defined MULTICORE_MEM_MANAGER) && (defined MULTICORE_BLACKBOX)
|
||||
return MEM_BufferFreeOnMaster(buffer);
|
||||
#elif (defined MULTICORE_MEM_MANAGER) && (defined MULTICORE_HOST)
|
||||
return MEM_BufferFreeOnSlave(buffer);
|
||||
#else
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
pParentPool = (pools_t *)pHeader->pParentPool;
|
||||
pool = memPools;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (pParentPool == pool)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(pool->nextBlockSize == 0)
|
||||
{
|
||||
/* The parent pool was not found! This means that the memory buffer is corrupt or
|
||||
that the MEM_BufferFree() function was called with an invalid parameter */
|
||||
#ifdef MEM_STATISTICS
|
||||
pParentPool->poolStatistics.freeFailures++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
OSA_InterruptEnable();
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
pool++;
|
||||
}
|
||||
|
||||
if( pHeader->link.list != NULL )
|
||||
{
|
||||
/* The memory buffer appears to be enqueued in a linked list.
|
||||
This list may be the free memory buffers pool, or another list. */
|
||||
#ifdef MEM_STATISTICS
|
||||
pParentPool->poolStatistics.freeFailures++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
OSA_InterruptEnable();
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
gFreeMessagesCount++;
|
||||
|
||||
ListAddTail((listHandle_t)&pParentPool->anchor, (listElementHandle_t)&pHeader->link);
|
||||
pParentPool->allocatedBlocks--;
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
MEM_ASSERT(pParentPool->poolStatistics.allocatedBlocks > 0);
|
||||
pParentPool->poolStatistics.allocatedBlocks--;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
MEM_Track(buffer, MEM_TRACKING_FREE_c, savedLR, 0, NULL);
|
||||
#endif /*MEM_TRACKING*/
|
||||
OSA_InterruptEnable();
|
||||
return MEM_SUCCESS_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Determines the size of a memory block
|
||||
*
|
||||
* \param[in] buffer - Pointer to buffer.
|
||||
*
|
||||
* \return size of memory block
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint16_t MEM_BufferGetSize
|
||||
(
|
||||
void* buffer /* IN: Block of memory to free*/
|
||||
)
|
||||
{
|
||||
if( buffer )
|
||||
{
|
||||
return ((pools_t *)((listHeader_t *)buffer-1)->pParentPool)->blockSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! *********************************************************************************
|
||||
* \brief This function updates the tracking array element corresponding to the given
|
||||
* block.
|
||||
*
|
||||
* \param[in] block - Pointer to the block.
|
||||
* \param[in] alloc - Indicates whether an allocation or free operation was performed
|
||||
* \param[in] address - Address where MEM_BufferAlloc or MEM_BufferFree was called
|
||||
* \param[in] requestedSize - Indicates the requested buffer size passed to MEM_BufferAlloc.
|
||||
* Has no use if a free operation was performed.
|
||||
*
|
||||
* \return Returns TRUE if correct allocation or dealocation was performed, FALSE if a
|
||||
* buffer was allocated or freed twice.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize, void *pCaller)
|
||||
{
|
||||
uint16_t i;
|
||||
blockTracking_t *pTrack = NULL;
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStat_t * poolStatistics = (poolStat_t *)&((pools_t *)( (listElementHandle_t)(block-1)->pParentPool ))->poolStatistics;
|
||||
#endif
|
||||
|
||||
for( i=0; i<mTotalNoOfMsgs_c; i++ )
|
||||
{
|
||||
if( block == memTrack[i].blockAddr )
|
||||
{
|
||||
pTrack = &memTrack[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !pTrack || pTrack->allocStatus == alloc)
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic( 0, (uint32_t)MEM_Track, 0, 0);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pTrack->allocStatus = alloc;
|
||||
pTrack->pCaller = (void*)((uint32_t)pCaller & 0x7FFFFFFF);
|
||||
|
||||
if(alloc == MEM_TRACKING_ALLOC_c)
|
||||
{
|
||||
pTrack->fragmentWaste = pTrack->blockSize - requestedSize;
|
||||
pTrack->allocCounter++;
|
||||
pTrack->allocAddr = (void *)address;
|
||||
if( (uint32_t)pCaller & 0x80000000 )
|
||||
{
|
||||
pTrack->timeStamp = 0xFFFFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTrack->timeStamp = MEM_GetTimeStamp();
|
||||
}
|
||||
#ifdef MEM_STATISTICS
|
||||
gTotalFragmentWaste += pTrack->fragmentWaste;
|
||||
if(gTotalFragmentWaste > gMaxTotalFragmentWaste)
|
||||
{
|
||||
gMaxTotalFragmentWaste = gTotalFragmentWaste;
|
||||
FLib_MemCpy(&memPoolsSnapShot[0], &memPools[0], sizeof(memPools));
|
||||
}
|
||||
|
||||
poolStatistics->poolFragmentWaste += pTrack->fragmentWaste;
|
||||
if(poolStatistics->poolFragmentWaste > poolStatistics->poolFragmentWastePeak)
|
||||
poolStatistics->poolFragmentWastePeak = poolStatistics->poolFragmentWaste;
|
||||
if(pTrack->fragmentWaste < poolStatistics->poolFragmentMinWaste)
|
||||
{
|
||||
poolStatistics->poolFragmentMinWaste = pTrack->fragmentWaste;
|
||||
}
|
||||
if(pTrack->fragmentWaste > poolStatistics->poolFragmentMaxWaste)
|
||||
{
|
||||
poolStatistics->poolFragmentMaxWaste = pTrack->fragmentWaste;
|
||||
}
|
||||
|
||||
if(poolStatistics->allocatedBlocks == poolStatistics->numBlocks)
|
||||
{
|
||||
//__asm("BKPT #0\n") ; /* cause the debugger to stop */
|
||||
}
|
||||
#endif /*MEM_STATISTICS*/
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStatistics->poolFragmentWaste -= pTrack->fragmentWaste;
|
||||
gTotalFragmentWaste -= pTrack->fragmentWaste;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
pTrack->fragmentWaste = 0;
|
||||
pTrack->freeCounter++;
|
||||
pTrack->freeAddr = (void *)address;
|
||||
pTrack->timeStamp = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function checks for buffer overflow when copying multiple bytes
|
||||
*
|
||||
* \param[in] p - pointer to destination.
|
||||
* \param[in] size - number of bytes to copy
|
||||
*
|
||||
* \return 1 if overflow detected, else 0
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size)
|
||||
{
|
||||
poolInfo_t *pPollInfo = poolInfo;
|
||||
uint8_t* memAddr = (uint8_t *)memHeap;
|
||||
uint32_t poolBytes, blockBytes, i;
|
||||
|
||||
if( (p < (uint8_t*)memHeap) || (p > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( pPollInfo->blockSize )
|
||||
{
|
||||
blockBytes = pPollInfo->blockSize + sizeof(listHeader_t);
|
||||
poolBytes = blockBytes * pPollInfo->poolSize;
|
||||
|
||||
/* Find the correct message pool */
|
||||
if( (p >= memAddr) && (p < memAddr + poolBytes) )
|
||||
{
|
||||
/* Check if the size to copy is greather then the size of the current block */
|
||||
if( size > pPollInfo->blockSize )
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic(0,0,0,0);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the correct memory block */
|
||||
for( i=0; i<pPollInfo->poolSize; i++ )
|
||||
{
|
||||
if( (p >= memAddr) && (p < memAddr + blockBytes) )
|
||||
{
|
||||
if( p + size > memAddr + blockBytes )
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic(0,0,0,0);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memAddr += blockBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* check next pool */
|
||||
memAddr += poolBytes;
|
||||
pPollInfo++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function checks if the buffers are allocated for more than the
|
||||
* specified duration
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
void MEM_CheckIfMemBuffersAreFreed(void)
|
||||
{
|
||||
uint32_t t;
|
||||
uint16_t i, j = 0;
|
||||
uint8_t trackCount = 0;
|
||||
pools_t *pParentPool;
|
||||
volatile blockTracking_t *pTrack;
|
||||
static volatile blockTracking_t *mpTrackTbl[NUM_OF_TRACK_PTR];
|
||||
static uint32_t lastTimestamp = 0;
|
||||
uint32_t currentTime = MEM_GetTimeStamp();
|
||||
|
||||
if( (currentTime - lastTimestamp) >= MEM_CheckMemBufferInterval_c )
|
||||
{
|
||||
lastTimestamp = currentTime;
|
||||
j = 0;
|
||||
|
||||
for( i = 0; i < mTotalNoOfMsgs_c; i++ )
|
||||
{
|
||||
pTrack = &memTrack[i];
|
||||
|
||||
/* Validate the pParent first */
|
||||
pParentPool = (((listHeader_t *)(pTrack->blockAddr))-1)->pParentPool;
|
||||
if(pParentPool != &memPools[j])
|
||||
{
|
||||
if(j < NumberOfElements(memPools))
|
||||
{
|
||||
j++;
|
||||
if(pParentPool != &memPools[j])
|
||||
{
|
||||
panic(0,0,0,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
panic(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if it should be freed */
|
||||
OSA_InterruptDisable();
|
||||
if((pTrack->timeStamp != 0xffffffff ) &&
|
||||
(pTrack->allocStatus == MEM_TRACKING_ALLOC_c) &&
|
||||
(currentTime > pTrack->timeStamp))
|
||||
{
|
||||
t = currentTime - pTrack->timeStamp;
|
||||
if( t > MEM_CheckMemBufferThreshold_c )
|
||||
{
|
||||
mpTrackTbl[trackCount++] = pTrack;
|
||||
if(trackCount == NUM_OF_TRACK_PTR)
|
||||
{
|
||||
(void)mpTrackTbl; /* remove compiler warnings */
|
||||
panic(0,0,0,0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
} /* end for */
|
||||
}
|
||||
}
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Get time-stamp for memory operation: alloc/free.
|
||||
*
|
||||
* \return dymmy time-stamp
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
__weak uint32_t MEM_GetTimeStamp(void)
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((weak)) uint32_t MEM_GetTimeStamp(void)
|
||||
#endif
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
#endif /* MEM_TRACKING */
|
||||
|
||||
|
||||
/*! ************************************************************************************************
|
||||
\brief MEM Manager calloc alternative implementation.
|
||||
|
||||
\param [in] len Number of blocks
|
||||
\param [in] size Size of one block
|
||||
|
||||
\return void* Pointer to the allocated buffer or NULL in case of error
|
||||
************************************************************************************************* */
|
||||
void* MEM_CallocAlt
|
||||
(
|
||||
size_t len,
|
||||
size_t val
|
||||
)
|
||||
{
|
||||
void *pData = MEM_BufferAllocForever (len* val, 0);
|
||||
if (pData)
|
||||
{
|
||||
FLib_MemSet (pData, 0, len* val);
|
||||
}
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
/*! ************************************************************************************************
|
||||
\brief MEM Manager free alternative implementation.
|
||||
|
||||
\param [in] pData Pointer to the allocated buffer
|
||||
|
||||
\return void
|
||||
************************************************************************************************* */
|
||||
void MEM_FreeAlt
|
||||
(
|
||||
void* pData
|
||||
)
|
||||
{
|
||||
MEM_BufferFree (pData);
|
||||
}
|
||||
third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h
Vendored
Executable
+612
@@ -0,0 +1,612 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
#ifndef _FSL_OS_ABSTRACTION_H_
|
||||
#define _FSL_OS_ABSTRACTION_H_
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_os_abstraction_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! @brief Type for the Task Priority*/
|
||||
typedef uint16_t osaTaskPriority_t;
|
||||
/*! @brief Type for the timer definition*/
|
||||
typedef enum {
|
||||
osaTimer_Once = 0, /*!< one-shot timer*/
|
||||
osaTimer_Periodic = 1 /*!< repeating timer*/
|
||||
} osaTimer_t;
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
|
||||
typedef void* osaTaskId_t;
|
||||
/*! @brief Type for the parameter to be passed to the task at its creation */
|
||||
typedef void* osaTaskParam_t;
|
||||
/*! @brief Type for task pointer. Task prototype declaration */
|
||||
typedef void (*osaTaskPtr_t) (osaTaskParam_t task_param);
|
||||
/*! @brief Type for the semaphore handler, returned by the OSA_SemaphoreCreate function. */
|
||||
typedef void* osaSemaphoreId_t;
|
||||
/*! @brief Type for the mutex handler, returned by the OSA_MutexCreate function. */
|
||||
typedef void* osaMutexId_t;
|
||||
/*! @brief Type for the event handler, returned by the OSA_EventCreate function. */
|
||||
typedef void* osaEventId_t;
|
||||
/*! @brief Type for an event flags group, bit 32 is reserved. */
|
||||
typedef uint32_t osaEventFlags_t;
|
||||
/*! @brief Message definition. */
|
||||
typedef void* osaMsg_t;
|
||||
/*! @brief Type for the message queue handler, returned by the OSA_MsgQCreate function. */
|
||||
typedef void* osaMsgQId_t;
|
||||
/*! @brief Type for the Timer handler, returned by the OSA_TimerCreate function. */
|
||||
typedef void *osaTimerId_t;
|
||||
/*! @brief Type for the Timer callback function pointer. */
|
||||
typedef void (*osaTimerFctPtr_t) (void const *argument);
|
||||
/*! @brief Thread Definition structure contains startup information of a thread.*/
|
||||
typedef struct osaThreadDef_tag {
|
||||
osaTaskPtr_t pthread; /*!< start address of thread function*/
|
||||
uint32_t tpriority; /*!< initial thread priority*/
|
||||
uint32_t instances; /*!< maximum number of instances of that thread function*/
|
||||
uint32_t stacksize; /*!< stack size requirements in bytes; 0 is default stack size*/
|
||||
uint32_t *tstack;
|
||||
void *tlink;
|
||||
uint8_t *tname;
|
||||
bool_t useFloat;
|
||||
} osaThreadDef_t;
|
||||
/*! @brief Thread Link Definition structure .*/
|
||||
typedef struct osaThreadLink_tag{
|
||||
uint8_t link[12];
|
||||
osaTaskId_t osThreadId;
|
||||
osaThreadDef_t *osThreadDefHandle;
|
||||
uint32_t *osThreadStackHandle;
|
||||
}osaThreadLink_t, *osaThreadLinkHandle_t;
|
||||
|
||||
/*! @Timer Definition structure contains timer parameters.*/
|
||||
typedef struct osaTimerDef_tag {
|
||||
osaTimerFctPtr_t pfCallback; /* < start address of a timer function */
|
||||
void *argument;
|
||||
} osaTimerDef_t;
|
||||
/*! @brief Defines the return status of OSA's functions */
|
||||
typedef enum osaStatus_tag
|
||||
{
|
||||
osaStatus_Success = 0U, /*!< Success */
|
||||
osaStatus_Error = 1U, /*!< Failed */
|
||||
osaStatus_Timeout = 2U, /*!< Timeout occurs while waiting */
|
||||
osaStatus_Idle = 3U /*!< Used for bare metal only, the wait object is not ready
|
||||
and timeout still not occur */
|
||||
}osaStatus_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if defined (FSL_RTOS_MQX)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_FREE_RTOS)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_UCOSII)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_UCOSIII)
|
||||
#define USE_RTOS 1
|
||||
#else
|
||||
#define USE_RTOS 0
|
||||
#endif
|
||||
|
||||
#define OSA_PRIORITY_IDLE (6)
|
||||
#define OSA_PRIORITY_LOW (5)
|
||||
#define OSA_PRIORITY_BELOW_NORMAL (4)
|
||||
#define OSA_PRIORITY_NORMAL (3)
|
||||
#define OSA_PRIORITY_ABOVE_NORMAL (2)
|
||||
#define OSA_PRIORITY_HIGH (1)
|
||||
#define OSA_PRIORITY_REAL_TIME (0)
|
||||
#define OSA_TASK_PRIORITY_MAX (0)
|
||||
#define OSA_TASK_PRIORITY_MIN (15)
|
||||
#define SIZE_IN_UINT32_UNITS(size) (((size) + sizeof(uint32_t) - 1) / sizeof(uint32_t))
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define osaWaitForever_c ((uint32_t)(-1))
|
||||
#define osaEventFlagsAll_c ((osaEventFlags_t)(0x00FFFFFF))
|
||||
#define osThreadStackArray(name) osThread_##name##_stack
|
||||
#define osThreadStackDef(name, stacksize, instances) \
|
||||
uint32_t osThreadStackArray(name)[SIZE_IN_UINT32_UNITS(stacksize)*(instances)];
|
||||
|
||||
/* ==== Thread Management ==== */
|
||||
|
||||
/* Create a Thread Definition with function, priority, and stack requirements.
|
||||
* \param name name of the thread function.
|
||||
* \param priority initial priority of the thread function.
|
||||
* \param instances number of possible thread instances.
|
||||
* \param stackSz stack size (in bytes) requirements for the thread function.
|
||||
* \param useFloat
|
||||
*/
|
||||
#if defined(FSL_RTOS_MQX)
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
osThreadLink_##name, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#elif defined (FSL_RTOS_UCOSII)
|
||||
#if gTaskMultipleInstancesManagement_c
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
osThreadLink_##name, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#else
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
NULL, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#endif
|
||||
#else
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#endif
|
||||
/* Access a Thread defintion.
|
||||
* \param name name of the thread definition object.
|
||||
*/
|
||||
#define OSA_TASK(name) \
|
||||
&os_thread_def_##name
|
||||
|
||||
#define OSA_TASK_PROTO(name) \
|
||||
extern osaThreadDef_t os_thread_def_##name
|
||||
/* ==== Timer Management ====
|
||||
* Define a Timer object.
|
||||
* \param name name of the timer object.
|
||||
* \param function name of the timer call back function.
|
||||
*/
|
||||
|
||||
#define OSA_TIMER_DEF(name, function) \
|
||||
osaTimerDef_t os_timer_def_##name = \
|
||||
{ (function), NULL }
|
||||
|
||||
/* Access a Timer definition.
|
||||
* \param name name of the timer object.
|
||||
*/
|
||||
#define OSA_TIMER(name) \
|
||||
&os_timer_def_##name
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
******************************************************************************
|
||||
* Public memory declarations
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
extern const uint8_t gUseRtos_c;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*!
|
||||
* @name Task management
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Creates a task.
|
||||
*
|
||||
* This function is used to create task based on the resources defined
|
||||
* by the macro OSA_TASK_DEFINE.
|
||||
*
|
||||
* @param thread_def pointer to the osaThreadDef_t structure which defines the task.
|
||||
* @param task_param Pointer to be passed to the task when it is created.
|
||||
*
|
||||
* @retval taskId The task is successfully created.
|
||||
* @retval NULL The task can not be created..
|
||||
*
|
||||
* Example:
|
||||
@code
|
||||
osaTaskId_t taskId;
|
||||
OSA_TASK_DEFINE( Job1, OSA_PRIORITY_HIGH, 1, 800, 0);;
|
||||
taskId = OSA__TaskCreate(OSA__TASK(Job1), (osaTaskParam_t)NULL);
|
||||
@endcode
|
||||
*/
|
||||
osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def, osaTaskParam_t task_param);
|
||||
|
||||
/*!
|
||||
* @brief Gets the handler of active task.
|
||||
*
|
||||
* @return Handler to current active task.
|
||||
*/
|
||||
osaTaskId_t OSA_TaskGetId(void);
|
||||
|
||||
/*!
|
||||
* @brief Puts the active task to the end of scheduler's queue.
|
||||
*
|
||||
* When a task calls this function, it gives up the CPU and puts itself to the
|
||||
* end of a task ready list.
|
||||
*
|
||||
* @retval osaStatus_Success The function is called successfully.
|
||||
* @retval osaStatus_Error Error occurs with this function.
|
||||
*/
|
||||
osaStatus_t OSA_TaskYield(void);
|
||||
|
||||
/*!
|
||||
* @brief Gets the priority of a task.
|
||||
*
|
||||
* @param taskId The handler of the task whose priority is received.
|
||||
*
|
||||
* @return Task's priority.
|
||||
*/
|
||||
osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId);
|
||||
|
||||
/*!
|
||||
* @brief Sets the priority of a task.
|
||||
*
|
||||
* @param taskId The handler of the task whose priority is set.
|
||||
* @param taskPriority The priority to set.
|
||||
*
|
||||
* @retval osaStatus_Success Task's priority is set successfully.
|
||||
* @retval osaStatus_Error Task's priority can not be set.
|
||||
*/
|
||||
osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority);
|
||||
/*!
|
||||
* @brief Destroys a previously created task.
|
||||
*
|
||||
* @param taskId The handler of the task to destroy. Returned by the OSA_TaskCreate function.
|
||||
*
|
||||
* @retval osaStatus_Success The task was successfully destroyed.
|
||||
* @retval osaStatus_Error Task destruction failed or invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId);
|
||||
|
||||
/*!
|
||||
* @brief Creates a semaphore with a given value.
|
||||
*
|
||||
* This function creates a semaphore and sets the value to the parameter
|
||||
* initValue.
|
||||
*
|
||||
* @param initValue Initial value the semaphore will be set to.
|
||||
*
|
||||
* @retval handler to the new semaphore if the semaphore is created successfully.
|
||||
* @retval NULL if the semaphore can not be created.
|
||||
*
|
||||
*
|
||||
*/
|
||||
osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created semaphore.
|
||||
*
|
||||
* @param semId Pointer to the semaphore to destroy.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is successfully destroyed.
|
||||
* @retval osaStatus_Error The semaphore can not be destroyed.
|
||||
*/
|
||||
osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId);
|
||||
|
||||
/*!
|
||||
* @brief Pending a semaphore with timeout.
|
||||
*
|
||||
* This function checks the semaphore's counting value. If it is positive,
|
||||
* decreases it and returns osaStatus_Success. Otherwise, a timeout is used
|
||||
* to wait.
|
||||
*
|
||||
* @param semId Pointer to the semaphore.
|
||||
* @param millisec The maximum number of milliseconds to wait if semaphore is not
|
||||
* positive. Pass osaWaitForever_c to wait indefinitely, pass 0
|
||||
* will return osaStatus_Timeout immediately.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is received.
|
||||
* @retval osaStatus_Timeout The semaphore is not received within the specified 'timeout'.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Signals for someone waiting on the semaphore to wake up.
|
||||
*
|
||||
* Wakes up one task that is waiting on the semaphore. If no task is waiting, increases
|
||||
* the semaphore's counting value.
|
||||
*
|
||||
* @param semId Pointer to the semaphore to signal.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is successfully signaled.
|
||||
* @retval osaStatus_Error The object can not be signaled or invalid parameter.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId);
|
||||
|
||||
/*!
|
||||
* @brief Create an unlocked mutex.
|
||||
*
|
||||
* This function creates a non-recursive mutex and sets it to unlocked status.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @retval handler to the new mutex if the mutex is created successfully.
|
||||
* @retval NULL if the mutex can not be created.
|
||||
*/
|
||||
osaMutexId_t OSA_MutexCreate(void);
|
||||
|
||||
/*!
|
||||
* @brief Waits for a mutex and locks it.
|
||||
*
|
||||
* This function checks the mutex's status. If it is unlocked, locks it and returns the
|
||||
* osaStatus_Success. Otherwise, waits for a timeout in milliseconds to lock.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
* @param millisec The maximum number of milliseconds to wait for the mutex.
|
||||
* If the mutex is locked, Pass the value osaWaitForever_c will
|
||||
* wait indefinitely, pass 0 will return osaStatus_Timeout
|
||||
* immediately.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is locked successfully.
|
||||
* @retval osaStatus_Timeout Timeout occurred.
|
||||
* @retval osaStatus_Error Incorrect parameter was passed.
|
||||
*
|
||||
* @note This is non-recursive mutex, a task can not try to lock the mutex it has locked.
|
||||
*/
|
||||
osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Unlocks a previously locked mutex.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is successfully unlocked.
|
||||
* @retval osaStatus_Error The mutex can not be unlocked or invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created mutex.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is successfully destroyed.
|
||||
* @retval osaStatus_Error The mutex can not be destroyed.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId);
|
||||
|
||||
/*!
|
||||
* @brief Initializes an event object with all flags cleared.
|
||||
*
|
||||
* This function creates an event object and set its clear mode. If autoClear
|
||||
* is TRUE, when a task gets the event flags, these flags will be
|
||||
* cleared automatically. Otherwise these flags must
|
||||
* be cleared manually.
|
||||
*
|
||||
* @param autoClear TRUE The event is auto-clear.
|
||||
* FALSE The event manual-clear
|
||||
* @retval handler to the new event if the event is created successfully.
|
||||
* @retval NULL if the event can not be created.
|
||||
*/
|
||||
osaEventId_t OSA_EventCreate(bool_t autoClear);
|
||||
|
||||
/*!
|
||||
* @brief Sets one or more event flags.
|
||||
*
|
||||
* Sets specified flags of an event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToSet Flags to be set.
|
||||
*
|
||||
* @retval osaStatus_Success The flags were successfully set.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet);
|
||||
|
||||
/*!
|
||||
* @brief Clears one or more flags.
|
||||
*
|
||||
* Clears specified flags of an event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToClear Flags to be clear.
|
||||
*
|
||||
* @retval osaStatus_Success The flags were successfully cleared.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear);
|
||||
|
||||
/*!
|
||||
* @brief Waits for specified event flags to be set.
|
||||
*
|
||||
* This function waits for a combination of flags to be set in an event object.
|
||||
* Applications can wait for any/all bits to be set. Also this function could
|
||||
* obtain the flags who wakeup the waiting task.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToWait Flags that to wait.
|
||||
* @param waitAll Wait all flags or any flag to be set.
|
||||
* @param millisec The maximum number of milliseconds to wait for the event.
|
||||
* If the wait condition is not met, pass osaWaitForever_c will
|
||||
* wait indefinitely, pass 0 will return osaStatus_Timeout
|
||||
* immediately.
|
||||
* @param setFlags Flags that wakeup the waiting task are obtained by this parameter.
|
||||
*
|
||||
* @retval osaStatus_Success The wait condition met and function returns successfully.
|
||||
* @retval osaStatus_Timeout Has not met wait condition within timeout.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
|
||||
*
|
||||
* @note Please pay attention to the flags bit width, FreeRTOS uses the most
|
||||
* significant 8 bis as control bits, so do not wait these bits while using
|
||||
* FreeRTOS.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
*
|
||||
* @retval osaStatus_Success The event is successfully destroyed.
|
||||
* @retval osaStatus_Error Event destruction failed.
|
||||
*/
|
||||
osaStatus_t OSA_EventDestroy(osaEventId_t eventId);
|
||||
|
||||
/*!
|
||||
* @brief Initializes a message queue.
|
||||
*
|
||||
* This function allocates memory for and initializes a message queue. Message queue elements are hardcoded as void*.
|
||||
*
|
||||
* @param msgNo :number of messages the message queue should accommodate.
|
||||
* This parameter should not exceed osNumberOfMessages defined in OSAbstractionConfig.h.
|
||||
*
|
||||
* @return: Handler to access the queue for put and get operations. If message queue
|
||||
* creation failed, return NULL.
|
||||
*/
|
||||
osaMsgQId_t OSA_MsgQCreate(uint32_t msgNo);
|
||||
|
||||
/*!
|
||||
* @brief Puts a message at the end of the queue.
|
||||
*
|
||||
* This function puts a message to the end of the message queue. If the queue
|
||||
* is full, this function returns the osaStatus_Error;
|
||||
*
|
||||
* @param msgQId pointer to queue returned by the OSA_MsgQCreate function.
|
||||
* @param pMessage Pointer to the message to be put into the queue.
|
||||
*
|
||||
* @retval osaStatus_Success Message successfully put into the queue.
|
||||
* @retval osaStatus_Error The queue was full or an invalid parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, osaMsg_t pMessage);
|
||||
|
||||
/*!
|
||||
* @brief Reads and remove a message at the head of the queue.
|
||||
*
|
||||
* This function gets a message from the head of the message queue. If the
|
||||
* queue is empty, timeout is used to wait.
|
||||
*
|
||||
* @param msgQId Queue handler returned by the OSA_MsgQCreate function.
|
||||
* @param pMessage Pointer to a memory to save the message.
|
||||
* @param millisec The number of milliseconds to wait for a message. If the
|
||||
* queue is empty, pass osaWaitForever_c will wait indefinitely,
|
||||
* pass 0 will return osaStatus_Timeout immediately.
|
||||
*
|
||||
* @retval osaStatus_Success Message successfully obtained from the queue.
|
||||
* @retval osaStatus_Timeout The queue remains empty after timeout.
|
||||
* @retval osaStatus_Error Invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, osaMsg_t pMessage, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created queue.
|
||||
*
|
||||
* @param msgQId queue handler returned by the OSA_MsgQCreate function.
|
||||
*
|
||||
* @retval osaStatus_Success The queue was successfully destroyed.
|
||||
* @retval osaStatus_Error Message queue destruction failed.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId);
|
||||
|
||||
/*!
|
||||
* @brief Enable all interrupts.
|
||||
*/
|
||||
void OSA_InterruptEnable(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable all interrupts.
|
||||
*/
|
||||
void OSA_InterruptDisable(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable interrupts except high-priority ones
|
||||
*
|
||||
* @param pu8OldIntLevel Variable to hold previous setting
|
||||
*/
|
||||
void OSA_InterruptEnableRestricted(uint32_t *pu32OldIntLevel);
|
||||
|
||||
/*!
|
||||
* @brief Restore interrupts that were previously restricted by a call
|
||||
* to OSA_InterruptEnableRestricted
|
||||
*
|
||||
* @param pu8OldIntLevel Variable holding previous setting
|
||||
*/
|
||||
void OSA_InterruptEnableRestore(uint32_t *pu32OldIntLevel);
|
||||
|
||||
/*!
|
||||
* @brief Enable all interrupts using PRIMASK.
|
||||
*/
|
||||
void OSA_EnableIRQGlobal(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable all interrupts using PRIMASK.
|
||||
*/
|
||||
void OSA_DisableIRQGlobal(void);
|
||||
|
||||
/*!
|
||||
* @brief Delays execution for a number of milliseconds.
|
||||
*
|
||||
* @param millisec The time in milliseconds to wait.
|
||||
*/
|
||||
void OSA_TimeDelay(uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief This function gets current time in milliseconds.
|
||||
*
|
||||
* @retval current time in milliseconds
|
||||
*/
|
||||
uint32_t OSA_TimeGetMsec(void);
|
||||
|
||||
/*!
|
||||
* @brief This function resets the current time to 0.
|
||||
*/
|
||||
void OSA_TimeResetMsec(void);
|
||||
|
||||
/*!
|
||||
* @brief Installs the interrupt handler.
|
||||
*
|
||||
* @param IRQNumber IRQ number of the interrupt.
|
||||
* @param handler The interrupt handler to install.
|
||||
*/
|
||||
void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void));
|
||||
|
||||
/*!
|
||||
* @brief Init the OSA time.
|
||||
*
|
||||
*/
|
||||
void OSA_TimeInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
Executable
+168
@@ -0,0 +1,168 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2013-2014, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
#if !defined(__FSL_OS_ABSTRACTION_BM_H__)
|
||||
#define __FSL_OS_ABSTRACTION_BM_H__
|
||||
|
||||
|
||||
/*!
|
||||
* @addtogroup os_abstraction_bm
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Bare Metal does not use timer. */
|
||||
#define FSL_OSA_BM_TIMER_NONE 0U
|
||||
|
||||
/*! @brief Bare Metal uses SYSTICK as timer. */
|
||||
#define FSL_OSA_BM_TIMER_SYSTICK 1U
|
||||
|
||||
/*! @brief Configure what timer is used in Bare Metal. */
|
||||
#ifndef FSL_OSA_BM_TIMER_CONFIG
|
||||
#define FSL_OSA_BM_TIMER_CONFIG FSL_OSA_BM_TIMER_NONE
|
||||
#endif
|
||||
|
||||
/*! @brief Type for an semaphore */
|
||||
typedef struct Semaphore
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this object */
|
||||
volatile uint8_t semCount; /*!< The count value of the object */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
} semaphore_t;
|
||||
|
||||
/*! @brief Type for a mutex */
|
||||
typedef struct Mutex
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this mutex */
|
||||
volatile bool_t isLocked; /*!< Is the object locked or not */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
} mutex_t;
|
||||
|
||||
/*! @brief Type for task parameter */
|
||||
typedef void* task_param_t;
|
||||
#define gIdleTaskPriority_c ((task_priority_t) 0)
|
||||
#define gInvalidTaskPriority_c ((task_priority_t) -1)
|
||||
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function */
|
||||
typedef void (* task_t)(task_param_t param);
|
||||
/*! @brief Task control block for bare metal. */
|
||||
typedef struct TaskControlBlock
|
||||
{
|
||||
osaTaskPtr_t p_func; /*!< Task's entry */
|
||||
bool_t haveToRun; /*!< Task was signaled */
|
||||
osaTaskPriority_t priority; /*!< Task's priority */
|
||||
osaTaskParam_t param; /*!< Task's parameter */
|
||||
struct TaskControlBlock *next; /*!< Pointer to next task control block */
|
||||
struct TaskControlBlock *prev; /*!< Pointer to previous task control block */
|
||||
} task_control_block_t;
|
||||
|
||||
/*! @brief Type for a task pointer */
|
||||
typedef task_control_block_t* task_handler_t;
|
||||
|
||||
/*! @brief Type for a task stack */
|
||||
typedef uint32_t task_stack_t;
|
||||
/*! @brief Type for an event flags group, bit 32 is reserved */
|
||||
typedef uint32_t event_flags_t;
|
||||
|
||||
|
||||
/*! @brief Type for an event object */
|
||||
typedef struct Event
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this event */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
volatile event_flags_t flags; /*!< The flags status */
|
||||
bool_t autoClear; /*!< Auto clear or manual clear */
|
||||
task_handler_t waitingTask; /*!< Handler to the waiting task */
|
||||
} event_t;
|
||||
|
||||
/*! @brief Type for a message queue */
|
||||
typedef struct MsgQueue
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout */
|
||||
uint16_t number; /*!< The number of messages in the queue */
|
||||
uint16_t max; /*!< The max number of queue messages */
|
||||
uint16_t head; /*!< Index of the next message to be read */
|
||||
uint16_t tail; /*!< Index of the next place to write to */
|
||||
uint32_t queueMem[osNumberOfMessages]; /*!< Points to the queue memory */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
task_handler_t waitingTask; /*!< Handler to the waiting task */
|
||||
}msg_queue_t;
|
||||
|
||||
/*! @brief Type for a message queue handler */
|
||||
typedef msg_queue_t* msg_queue_handler_t;
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define OSA_WAIT_FOREVER 0xFFFFFFFFU
|
||||
|
||||
/*! @brief How many tasks can the bare metal support. */
|
||||
#define TASK_MAX_NUM 7
|
||||
|
||||
/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */
|
||||
#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR))
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
extern void DefaultISR(void);
|
||||
|
||||
/*!
|
||||
* @name Thread management
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Defines a task.
|
||||
*
|
||||
* This macro defines resources for a task statically. Then, the OSA_TaskCreate
|
||||
* creates the task based-on these resources.
|
||||
*
|
||||
* @param task The task function.
|
||||
* @param stackSize The stack size this task needs in bytes.
|
||||
*/
|
||||
|
||||
#define PRIORITY_OSA_TO_RTOS(osa_prio) (osa_prio)
|
||||
#define PRIORITY_RTOS_TO_OSA(rtos_prio) (rtos_prio)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief Calls all task functions one time except for the current task.
|
||||
*
|
||||
* This function calls all other task functions one time. If current
|
||||
* task is waiting for an event triggered by other tasks, this function
|
||||
* could be used to trigger the event.
|
||||
*
|
||||
* @note There should be only one task calls this function, if more than
|
||||
* one task call this function, stack overflow may occurs. Be careful
|
||||
* to use this function.
|
||||
*
|
||||
*/
|
||||
void OSA_PollAllOtherTasks(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* __FSL_OS_ABSTRACTION_BM_H__ */
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
||||
Vendored
Executable
+53
@@ -0,0 +1,53 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
#ifndef _FSL_OS_ABSTRACTION_CONFIG_H_
|
||||
#define _FSL_OS_ABSTRACTION_CONFIG_H_
|
||||
|
||||
#ifndef osNumberOfSemaphores
|
||||
#define osNumberOfSemaphores 5
|
||||
#endif
|
||||
#ifndef osNumberOfMutexes
|
||||
#define osNumberOfMutexes 5
|
||||
#endif
|
||||
#ifndef osNumberOfMessageQs
|
||||
#define osNumberOfMessageQs 0
|
||||
#endif
|
||||
#ifndef osNumberOfMessages
|
||||
#define osNumberOfMessages 10
|
||||
#endif
|
||||
#ifndef osNumberOfEvents
|
||||
#define osNumberOfEvents 5
|
||||
#endif
|
||||
|
||||
#ifndef CPU_JN518X
|
||||
#ifndef gMainThreadStackSize_c
|
||||
#define gMainThreadStackSize_c 1024
|
||||
#endif
|
||||
#else
|
||||
#if !defined gMainThreadStackSize_c || (gMainThreadStackSize_c < 1200)
|
||||
#undef gMainThreadStackSize_c
|
||||
#define gMainThreadStackSize_c 1200
|
||||
#endif
|
||||
#endif
|
||||
#ifndef gMainThreadPriority_c
|
||||
#define gMainThreadPriority_c 7
|
||||
#endif
|
||||
|
||||
#ifndef gTaskMultipleInstancesManagement_c
|
||||
#define gTaskMultipleInstancesManagement_c 0
|
||||
#endif
|
||||
|
||||
#ifndef osCustomStartup
|
||||
#define osCustomStartup 0
|
||||
#endif
|
||||
|
||||
#endif /* _FSL_OS_ABSTRACTION_CONFIG_H_ */
|
||||
Vendored
Executable
+161
@@ -0,0 +1,161 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2013-2014, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
#if !defined(__FSL_OS_ABSTRACTION_FREERTOS_H__)
|
||||
#define __FSL_OS_ABSTRACTION_FREERTOS_H__
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ICC__ )
|
||||
/**
|
||||
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
|
||||
* http://supp.iar.com/Support/?note=24725
|
||||
*/
|
||||
#define MISRAC_DISABLE _Pragma ("diag_suppress= \
|
||||
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
|
||||
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
|
||||
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
|
||||
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
|
||||
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
|
||||
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
|
||||
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
|
||||
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
|
||||
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
|
||||
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
|
||||
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
|
||||
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
|
||||
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
|
||||
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
|
||||
Pm155")
|
||||
|
||||
#define MISRAC_ENABLE _Pragma ("diag_default= \
|
||||
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
|
||||
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
|
||||
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
|
||||
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
|
||||
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
|
||||
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
|
||||
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
|
||||
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
|
||||
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
|
||||
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
|
||||
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
|
||||
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
|
||||
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
|
||||
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
|
||||
Pm155")
|
||||
#else
|
||||
/* Empty MISRA C macros for other toolchains. */
|
||||
#define MISRAC_DISABLE
|
||||
#define MISRAC_ENABLE
|
||||
#endif
|
||||
|
||||
MISRAC_DISABLE
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "event_groups.h"
|
||||
MISRAC_ENABLE
|
||||
|
||||
/*!
|
||||
* @addtogroup os_abstraction_free_rtos
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
|
||||
typedef TaskHandle_t task_handler_t;
|
||||
|
||||
/*! @brief Type for a task stack.*/
|
||||
typedef portSTACK_TYPE task_stack_t;
|
||||
|
||||
/*! @brief Type for task parameter */
|
||||
typedef void* task_param_t;
|
||||
|
||||
/*! @brief Type for a task function. */
|
||||
typedef pdTASK_CODE task_t;
|
||||
|
||||
/*! @brief Type for a mutex. */
|
||||
typedef xSemaphoreHandle mutex_t;
|
||||
|
||||
/*! @brief Type for a semaphore. */
|
||||
typedef xSemaphoreHandle semaphore_t;
|
||||
|
||||
/*! @brief Type for an event flags object.*/
|
||||
typedef EventBits_t event_flags_t;
|
||||
|
||||
/*! @brief Type for an event group object in FreeRTOS OS */
|
||||
typedef struct EventFreertos {
|
||||
bool_t autoClear; /*!< Auto clear or manual clear */
|
||||
EventGroupHandle_t eventHandler; /*!< FreeRTOS OS event handler */
|
||||
} event_freertos;
|
||||
|
||||
/*! @brief Type for an event group object */
|
||||
typedef event_freertos event_t;
|
||||
|
||||
/*! @brief Type for a message queue declaration and creation. */
|
||||
typedef xQueueHandle msg_queue_t;
|
||||
|
||||
/*! @brief Type for a message queue handler */
|
||||
typedef xQueueHandle msg_queue_handler_t;
|
||||
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define OSA_WAIT_FOREVER 0xFFFFFFFFU
|
||||
|
||||
/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */
|
||||
#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR))
|
||||
|
||||
/*! @brief The Max depth of Enter/Exist Critical could be nested in interrupt. */
|
||||
#define OSA_MAX_ISR_CRITICAL_SECTION_DEPTH 0x8U
|
||||
|
||||
extern void DefaultISR(void);
|
||||
|
||||
/*!
|
||||
* @name Thread management
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* @brief To provide unified task piority for upper layer, OSA layer makes conversion.
|
||||
*/
|
||||
#define PRIORITY_OSA_TO_RTOS(osa_prio) (configMAX_PRIORITIES - (osa_prio) -2)
|
||||
#define PRIORITY_RTOS_TO_OSA(rtos_prio) (configMAX_PRIORITIES - (rtos_prio) -2)
|
||||
|
||||
/* @}*/
|
||||
|
||||
|
||||
/*!
|
||||
* @name Message queues
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief This macro statically reserves the memory required for the queue.
|
||||
*
|
||||
* @param name Identifier for the memory region.
|
||||
* @param number Number of elements in the queue.
|
||||
* @param size Size of every elements in words.
|
||||
*/
|
||||
#define MSG_QUEUE_DECLARE(name, number, size) \
|
||||
msg_queue_t *name = NULL
|
||||
|
||||
/* @}*/
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif // __FSL_OS_ABSTRACTION_FREERTOS_H__
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
||||
third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c
Vendored
Executable
+1527
File diff suppressed because it is too large
Load Diff
Vendored
Executable
+1173
File diff suppressed because it is too large
Load Diff
+485
@@ -0,0 +1,485 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE: Persistent Data Manager
|
||||
*
|
||||
* DESCRIPTION: Provide management of data which needs to persist over
|
||||
* cold or warm start
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5148, JN5142, JN5139].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2012. All rights reserved
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PDM_H_INCLUDED
|
||||
#define PDM_H_INCLUDED
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Include Files ***/
|
||||
/****************************************************************************/
|
||||
|
||||
#define PUBLIC
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @addtogroup PDM library
|
||||
* @{
|
||||
*/
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
#define PDM_EXTERNAL_FLASH
|
||||
#endif
|
||||
#define PDM_NUM_BLOCKS 128
|
||||
#ifdef PDM_EXTERNAL_FLASH
|
||||
#define PDM_NAME_SIZE 16
|
||||
#else
|
||||
#define PDM_NAME_SIZE 7
|
||||
#ifndef PDM_USER_SUPPLIED_ID
|
||||
#define PDM_USER_SUPPLIED_ID /* Defaulting to having this enabled */
|
||||
#endif
|
||||
#endif
|
||||
#define PDM_INVALID_ID ((uint16)(-1))
|
||||
|
||||
/* PDM ID range allocation reservations
|
||||
* Each PDM_ID_BASE_xxx below is the base value for a block of 256 (0x100) IDs.
|
||||
* Within a module the individual IDs used by that module will be an offset from
|
||||
* this base.
|
||||
*
|
||||
* These ID ranges should not be re-used by other modules, even if the modules
|
||||
* are not both present in the build.
|
||||
*
|
||||
* Values should not be changed. Reserve a new range instead of changing an
|
||||
* existing range.
|
||||
*/
|
||||
#define PDM_ID_BASE_APP_ZB (0x0000) /* 0x0000?0x00ff: ZigBee Application Notes */
|
||||
#define PDM_ID_BASE_ZPSAPL (0xf000) /* 0xf000?0xf0ff: ZigBee ZPS APL layer */
|
||||
#define PDM_ID_BASE_ZPSNWK (0xf100) /* 0xf100?0xf1ff: ZigBee ZPS NWK layer */
|
||||
#define PDM_ID_BASE_RADIO (0xff00) /* 0xff00?0xffff: Radio driver */
|
||||
|
||||
/* PDM ID individual allocation reservations
|
||||
* Each PDM_ID_xxx below is an individual ID within one of the reserved ranges.
|
||||
* Individual IDs need to be declared here only if they are shared between modules.
|
||||
* Please include a descriptive comment to aid accurate identification.
|
||||
*/
|
||||
#define PDM_ID_RADIO_SETTINGS (PDM_ID_BASE_RADIO + 0x0000) /* Holds radio KMOD calibration data */
|
||||
|
||||
/* Defined because still using heap in PDM builds */
|
||||
#define PDM_USE_HEAP
|
||||
|
||||
#if (defined PDM_USE_HEAP)
|
||||
/* Empty declaration: buffer not needed */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments)
|
||||
#else
|
||||
/* Macro to create a static block of RAM to use instead of heap
|
||||
NOTE: Must be declared at module scope, not within a function
|
||||
NOTE: Value of 12 is based on size of tsPDM_FileSystemRecord */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments) \
|
||||
PUBLIC uint8 au8PDM_HeapBuffer[(u8NumberOfSegments) * 12] __attribute__((aligned (4)))
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_E_STATUS_OK,
|
||||
PDM_E_STATUS_INVLD_PARAM,
|
||||
// NVM based PDM codes
|
||||
PDM_E_STATUS_PDM_FULL,
|
||||
PDM_E_STATUS_NOT_SAVED,
|
||||
PDM_E_STATUS_RECOVERED,
|
||||
PDM_E_STATUS_PDM_RECOVERED_NOT_SAVED,
|
||||
PDM_E_STATUS_USER_BUFFER_SIZE,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_NO_INCREMENT,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_OK,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_COMPLETE,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_INCOMPLETE,
|
||||
PDM_E_STATUS_INTERNAL_ERROR
|
||||
} PDM_teStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_RECOVERY_STATE_NONE = 0,
|
||||
PDM_RECOVERY_STATE_NEW, // 1
|
||||
PDM_RECOVERY_STATE_RECOVERED, // 2
|
||||
PDM_RECOVERY_STATE_RECOVERED_NOT_READ, // 3
|
||||
PDM_RECOVERY_STATE_SAVED, // 4
|
||||
PDM_RECOVERY_STATE_NOT_SAVED, // 5
|
||||
PDM_RECOVERY_STATE_APPENDED, // 6
|
||||
// do not move
|
||||
PDM_RECOVERY_STATE_NUMBER
|
||||
} PDM_teRecoveryState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* this function gets called after a cold or warm start */
|
||||
void (*prInitHwCb)(void);
|
||||
|
||||
/* this function gets called to erase the given sector */
|
||||
void (*prEraseCb)(uint8_t u8Sector);
|
||||
|
||||
/* this function gets called to write data to an addresss
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prWriteCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
|
||||
/* this function gets called to read data from an address
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prReadCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
} PDM_tsHwFncTable;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_TRIGGER_VALUE_REACHED = 0,
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_MAXIMUM_REACHED,
|
||||
E_PDM_SYSTEM_EVENT_SAVE_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_NOT_ENOUGH_SPACE,
|
||||
E_PDM_SYSTEM_EVENT_LARGEST_RECORD_FULL_SAVE_NO_LONGER_POSSIBLE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_CHECKSUM_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_SAVE_OK,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_READ_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_WRITE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_ERASE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_CHECK_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_DATA_WRITE_FAIL,
|
||||
// nerdy event codes
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIRED,
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIR_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_INTERNAL_BUFFER_WEAR_COUNT_SWAP,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_DUPLICATE_FILE_SEGMENT_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_ERROR,
|
||||
// used in test harness
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_PREWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_POSTWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_DUPLICATE_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_VERIFY_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SMART_SAVE,
|
||||
E_PDM_SYSTEM_EVENT_FULL_SAVE
|
||||
} PDM_eSystemEventCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32eventNumber;
|
||||
PDM_eSystemEventCode eSystemEventCode;
|
||||
} PDM_tfpSystemEventCallback;
|
||||
|
||||
typedef void (*PDM_tpfvSystemEventCallback)(uint32_t u32eventNumber, PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Initialise the PDM
|
||||
*
|
||||
* This function is to be called in order to initialise the PDM module
|
||||
* call this EVERY cold start and EVERY warm start
|
||||
*
|
||||
* @param u16StartSegment: Start segment in flash
|
||||
* @param u8NumberOfSegments: number of contiguous segments from u16StartSegment
|
||||
* that belong to the PDM NVM space.
|
||||
* @param fpvPDM_SystemEventCallback: function pointer passed by using layer
|
||||
* to be notified of events/errors
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success PDM_E_STATUS_INTERNAL_ERROR otherwise
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eInitialise(uint16_t u16StartSegment,
|
||||
uint8_t u8NumberOfSegments,
|
||||
PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record
|
||||
*
|
||||
* This function saves the specified application data from RAM to the specified record
|
||||
* in NVM. The record is identified by means of a 16-bit user-defined value.
|
||||
* When a data record is saved to the NVM for the first time, the data is written provided
|
||||
* there are enough NVM segments available to hold the data. Upon subsequent save
|
||||
* requests, if there has been a change between the RAM-based and NVM-based data
|
||||
* buffers then the PDM will attempt to re-save only the segments that have changed
|
||||
* (if no data has changed, no save will be performed). This is advantageous due to the
|
||||
* restricted size of the NVM and the constraint that old data must be preserved while
|
||||
* saving changed data to the NVM.
|
||||
* Provided that you have registered a callback function with the PDM (see Section 6.3),
|
||||
* the callback mechanism will signal when a save has failed. Upon failure, the callback
|
||||
* function will be invoked and pass the event E_PDM_SYSTEM_EVENT_DESCRIPTOR_SAVE_FAILED
|
||||
* to the application
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (specified record ID is invalid)
|
||||
* @retval PDM_E_STATUS_NOT_SAVED (save to NVM failed)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordData(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record next time in idle task
|
||||
*
|
||||
* Like PDM_eSaveRecordData, except that the record information is queued to
|
||||
* saved in the idle task, when PDM_vIdleTask is called. Note that if the
|
||||
* internal queue is full, the first record on the queue is saved immediately
|
||||
* to make space for this record.
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordDataInIdleTask(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save queued PDM records
|
||||
*
|
||||
* Synchronously saves any queued record writes that have been generated by
|
||||
* calls to PDM_eSaveRecordDataInIdleTask. To avoid this function taking too
|
||||
* much time, the number of records that can be written can be limited by
|
||||
* the u8WritesAllowed parameter. Use a value of 255 to effectively avoid
|
||||
* this limit.
|
||||
* @param u8WritesAllowed Maximum number of records that can be written
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vIdleTask(uint8_t u8WritesAllowed);
|
||||
|
||||
/*!
|
||||
* @brief Purge the pending event available in the queue
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vQueuePurge(void);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Reads Partial Data from an Existing Record in the File System
|
||||
*
|
||||
* This function appends data to a record previously written.
|
||||
* The record is identified by means of a 16-bit user-defined value.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read from
|
||||
* @param u16TableOffset Data Offset
|
||||
* @param pu8DataBuffer Data Buffer
|
||||
* @param u16DataLength Length of input data, in bytes.
|
||||
* @param pu16DataBytesRead Number Of Data Bytes Read u16IdValue
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (error in arguments)
|
||||
* @retval PDM_E_STATUS_INTERNAL_ERROR
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadPartialDataFromExistingRecord(uint16_t u16IdValue,
|
||||
uint16_t u16TableOffset,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function reads the specified record of application data from the NVM and stores
|
||||
* the read data in the supplied data buffer in RAM. The record is specified using its
|
||||
* unique 16-bit identifier.
|
||||
* Before calling this function, it may be useful to call PDM_bDoesDataExist() in order
|
||||
* to determine whether a record with the specified identifier exists in the EEPROM and,
|
||||
* if it does, to obtain its size.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read
|
||||
* @param pvDataBuffer Pointer to the data buffer in RAM where the read data is to
|
||||
* be stored
|
||||
* @param u16DataBufferLength Length of the data buffer, in bytes
|
||||
* @param pu16DataBytesRead Pointer to a location to receive the number of data bytes
|
||||
* read
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM otherwise i.e. specified record ID is invalid
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadDataFromRecord(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes the specified record of application data in NVM.
|
||||
* @see PDM_eDeleteAllData to alternatively delete all records in NVM
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be deleted
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteDataRecord(uint16_t u16IdValue);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes all records in NVM, including both application data and stack
|
||||
* context data, resulting in an empty PDM file system. The NVM segment Wear Count
|
||||
* values are preserved (and incremented) throughout this function call.
|
||||
* This function is to be used with extreme care in a Zigbee application context
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteAllDataRecords(void);
|
||||
|
||||
/*!
|
||||
* @brief Seeks for a certain record by record identifier
|
||||
*
|
||||
* This function checks whether data associated with thd specified record ID
|
||||
* exists in the NVM. If the data record exists, the function returns the data
|
||||
* length, in bytes, in a location to which a pointer must be provided.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be found
|
||||
* @param pu16DataLength Pointer to location to receive length, in bytes,
|
||||
* of data record (if any) associated with specified record ID
|
||||
*
|
||||
* @retval true if record was fond false otherwise
|
||||
*/
|
||||
PUBLIC bool_t PDM_bDoesDataExist(uint16_t u16IdValue, uint16_t *pu16DataLength);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are left in the PDM space
|
||||
*
|
||||
* This function returns the number of unused segments that remain in the NVM.
|
||||
* Note that the returned parameter being a uint8_t the total expected number of
|
||||
* segments cannot exceed 255
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of PDM NVM segments free
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentCapacity(void);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are occupied in the PDM space
|
||||
*
|
||||
* This function returns the number of used segments in the NVM
|
||||
* @see PDM_u8GetSegmentCapacity
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of NVM segments used
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentOccupancy(void);
|
||||
|
||||
/*!
|
||||
* @brief Register a User defined system callback function
|
||||
*
|
||||
* This function registers a callback function that will be called in error events
|
||||
* @see PDM_pfGetSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param fpvPDM_SystemEventCallback function to replace the one that was set on PDM initialisation
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vRegisterSystemCallback(PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the previously defined system callback function
|
||||
*
|
||||
* This function retrieves the callback function that has been set by PDM_eInitialise
|
||||
* or PDM_vRegisterSystemCallback
|
||||
* @see PDM_vRegisterSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval fpvPDM_SystemEventCallback function used to notify error events
|
||||
*/
|
||||
PUBLIC PDM_tpfvSystemEventCallback PDM_pfGetSystemCallback(void);
|
||||
|
||||
PUBLIC void PDM_vSetWearCountTriggerLevel(uint32_t u32WearCountTriggerLevel);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetSegmentWearCount(uint8_t u8SegmentIndex, uint32_t *pu32WearCount);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetDeviceWearCountProfile(uint32_t au32WearCount[], uint8_t u8NumberOfSegments);
|
||||
|
||||
PUBLIC void PDM_vSetWearLevelDifference(uint32_t u32WearLevelDifference);
|
||||
|
||||
int PDM_Init(void);
|
||||
|
||||
#if defined UART_DEBUG
|
||||
PUBLIC void vPDM_InitialiseDisplayDataInFileSystem(uint16_t *pau16PDMFileIDrecord, uint8_t u8NumberOfPDMSegments);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInFileSystem(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayDataWithIdInFileSystem(uint16_t u16IdValue);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInNVM(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayNVMsegmentData(uint8_t u8SegmentIndex);
|
||||
|
||||
PUBLIC char *psPDM_PrintEventID(PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
PUBLIC int iPDM_ReadRawNVMsegmentDataToBuffer(uint8_t u8SegmentIndex,
|
||||
uint8_t *pu8SegmentDataBuffer,
|
||||
uint16_t *pu16SegmentDataSize);
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
extern PUBLIC const uint32_t PDM_g_u32Version;
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /*PDM_H_INCLUDED*/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** END OF FILE ***/
|
||||
/****************************************************************************/
|
||||
BIN
Binary file not shown.
+488
@@ -0,0 +1,488 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE: Persistent Data Manager
|
||||
*
|
||||
* DESCRIPTION: Provide management of data which needs to persist over
|
||||
* cold or warm start
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5148, JN5142, JN5139].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2012. All rights reserved
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PDM_H_INCLUDED
|
||||
#define PDM_H_INCLUDED
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Include Files ***/
|
||||
/****************************************************************************/
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
#define PUBLIC
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @addtogroup PDM library
|
||||
* @{
|
||||
*/
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
#define PDM_EXTERNAL_FLASH
|
||||
#endif
|
||||
#define PDM_NUM_BLOCKS 128
|
||||
#ifdef PDM_EXTERNAL_FLASH
|
||||
#define PDM_NAME_SIZE 16
|
||||
#else
|
||||
#define PDM_NAME_SIZE 7
|
||||
#ifndef PDM_USER_SUPPLIED_ID
|
||||
#define PDM_USER_SUPPLIED_ID /* Defaulting to having this enabled */
|
||||
#endif
|
||||
#endif
|
||||
#define PDM_INVALID_ID ((uint16)(-1))
|
||||
|
||||
/* PDM ID range allocation reservations
|
||||
* Each PDM_ID_BASE_xxx below is the base value for a block of 256 (0x100) IDs.
|
||||
* Within a module the individual IDs used by that module will be an offset from
|
||||
* this base.
|
||||
*
|
||||
* These ID ranges should not be re-used by other modules, even if the modules
|
||||
* are not both present in the build.
|
||||
*
|
||||
* Values should not be changed. Reserve a new range instead of changing an
|
||||
* existing range.
|
||||
*/
|
||||
#define PDM_ID_BASE_APP_ZB (0x0000) /* 0x0000?0x00ff: ZigBee Application Notes */
|
||||
#define PDM_ID_BASE_ZPSAPL (0xf000) /* 0xf000?0xf0ff: ZigBee ZPS APL layer */
|
||||
#define PDM_ID_BASE_ZPSNWK (0xf100) /* 0xf100?0xf1ff: ZigBee ZPS NWK layer */
|
||||
#define PDM_ID_BASE_RADIO (0xff00) /* 0xff00?0xffff: Radio driver */
|
||||
|
||||
/* PDM ID individual allocation reservations
|
||||
* Each PDM_ID_xxx below is an individual ID within one of the reserved ranges.
|
||||
* Individual IDs need to be declared here only if they are shared between modules.
|
||||
* Please include a descriptive comment to aid accurate identification.
|
||||
*/
|
||||
#define PDM_ID_RADIO_SETTINGS (PDM_ID_BASE_RADIO + 0x0000) /* Holds radio KMOD calibration data */
|
||||
|
||||
/* Defined because still using heap in PDM builds */
|
||||
#define PDM_USE_HEAP
|
||||
|
||||
#if (defined PDM_USE_HEAP)
|
||||
/* Empty declaration: buffer not needed */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments)
|
||||
#else
|
||||
/* Macro to create a static block of RAM to use instead of heap
|
||||
NOTE: Must be declared at module scope, not within a function
|
||||
NOTE: Value of 12 is based on size of tsPDM_FileSystemRecord */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments) \
|
||||
PUBLIC uint8 au8PDM_HeapBuffer[(u8NumberOfSegments) * 12] __attribute__((aligned (4)))
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_E_STATUS_OK,
|
||||
PDM_E_STATUS_INVLD_PARAM,
|
||||
// NVM based PDM codes
|
||||
PDM_E_STATUS_PDM_FULL,
|
||||
PDM_E_STATUS_NOT_SAVED,
|
||||
PDM_E_STATUS_RECOVERED,
|
||||
PDM_E_STATUS_PDM_RECOVERED_NOT_SAVED,
|
||||
PDM_E_STATUS_USER_BUFFER_SIZE,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_NO_INCREMENT,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_OK,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_COMPLETE,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_INCOMPLETE,
|
||||
PDM_E_STATUS_INTERNAL_ERROR
|
||||
} PDM_teStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_RECOVERY_STATE_NONE = 0,
|
||||
PDM_RECOVERY_STATE_NEW, // 1
|
||||
PDM_RECOVERY_STATE_RECOVERED, // 2
|
||||
PDM_RECOVERY_STATE_RECOVERED_NOT_READ, // 3
|
||||
PDM_RECOVERY_STATE_SAVED, // 4
|
||||
PDM_RECOVERY_STATE_NOT_SAVED, // 5
|
||||
PDM_RECOVERY_STATE_APPENDED, // 6
|
||||
// do not move
|
||||
PDM_RECOVERY_STATE_NUMBER
|
||||
} PDM_teRecoveryState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* this function gets called after a cold or warm start */
|
||||
void (*prInitHwCb)(void);
|
||||
|
||||
/* this function gets called to erase the given sector */
|
||||
void (*prEraseCb)(uint8_t u8Sector);
|
||||
|
||||
/* this function gets called to write data to an addresss
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prWriteCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
|
||||
/* this function gets called to read data from an address
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prReadCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
} PDM_tsHwFncTable;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_TRIGGER_VALUE_REACHED = 0,
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_MAXIMUM_REACHED,
|
||||
E_PDM_SYSTEM_EVENT_SAVE_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_NOT_ENOUGH_SPACE,
|
||||
E_PDM_SYSTEM_EVENT_LARGEST_RECORD_FULL_SAVE_NO_LONGER_POSSIBLE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_CHECKSUM_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_SAVE_OK,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_READ_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_WRITE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_ERASE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_CHECK_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_DATA_WRITE_FAIL,
|
||||
// nerdy event codes
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIRED,
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIR_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_INTERNAL_BUFFER_WEAR_COUNT_SWAP,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_DUPLICATE_FILE_SEGMENT_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_ERROR,
|
||||
// used in test harness
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_PREWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_POSTWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_DUPLICATE_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_VERIFY_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SMART_SAVE,
|
||||
E_PDM_SYSTEM_EVENT_FULL_SAVE
|
||||
} PDM_eSystemEventCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32eventNumber;
|
||||
PDM_eSystemEventCode eSystemEventCode;
|
||||
} PDM_tfpSystemEventCallback;
|
||||
|
||||
typedef void (*PDM_tpfvSystemEventCallback)(uint32_t u32eventNumber, PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Initialise the PDM
|
||||
*
|
||||
* This function is to be called in order to initialise the PDM module
|
||||
* call this EVERY cold start and EVERY warm start
|
||||
*
|
||||
* @param u16StartSegment: Start segment in flash
|
||||
* @param u8NumberOfSegments: number of contiguous segments from u16StartSegment
|
||||
* that belong to the PDM NVM space.
|
||||
* @param fpvPDM_SystemEventCallback: function pointer passed by using layer
|
||||
* to be notified of events/errors
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success PDM_E_STATUS_INTERNAL_ERROR otherwise
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eInitialise(uint16_t u16StartSegment,
|
||||
uint8_t u8NumberOfSegments,
|
||||
PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record
|
||||
*
|
||||
* This function saves the specified application data from RAM to the specified record
|
||||
* in NVM. The record is identified by means of a 16-bit user-defined value.
|
||||
* When a data record is saved to the NVM for the first time, the data is written provided
|
||||
* there are enough NVM segments available to hold the data. Upon subsequent save
|
||||
* requests, if there has been a change between the RAM-based and NVM-based data
|
||||
* buffers then the PDM will attempt to re-save only the segments that have changed
|
||||
* (if no data has changed, no save will be performed). This is advantageous due to the
|
||||
* restricted size of the NVM and the constraint that old data must be preserved while
|
||||
* saving changed data to the NVM.
|
||||
* Provided that you have registered a callback function with the PDM (see Section 6.3),
|
||||
* the callback mechanism will signal when a save has failed. Upon failure, the callback
|
||||
* function will be invoked and pass the event E_PDM_SYSTEM_EVENT_DESCRIPTOR_SAVE_FAILED
|
||||
* to the application
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (specified record ID is invalid)
|
||||
* @retval PDM_E_STATUS_NOT_SAVED (save to NVM failed)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordData(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record next time in idle task
|
||||
*
|
||||
* Like PDM_eSaveRecordData, except that the record information is queued to
|
||||
* saved in the idle task, when PDM_vIdleTask is called. Note that if the
|
||||
* internal queue is full, the first record on the queue is saved immediately
|
||||
* to make space for this record.
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordDataInIdleTask(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save queued PDM records
|
||||
*
|
||||
* Synchronously saves any queued record writes that have been generated by
|
||||
* calls to PDM_eSaveRecordDataInIdleTask. To avoid this function taking too
|
||||
* much time, the number of records that can be written can be limited by
|
||||
* the u8WritesAllowed parameter. Use a value of 255 to effectively avoid
|
||||
* this limit.
|
||||
* @param u8WritesAllowed Maximum number of records that can be written
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vIdleTask(uint8_t u8WritesAllowed);
|
||||
|
||||
/*!
|
||||
* @brief Purge the pending event available in the queue
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vQueuePurge(void);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Reads Partial Data from an Existing Record in the File System
|
||||
*
|
||||
* This function appends data to a record previously written.
|
||||
* The record is identified by means of a 16-bit user-defined value.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read from
|
||||
* @param u16TableOffset Data Offset
|
||||
* @param pu8DataBuffer Data Buffer
|
||||
* @param u16DataLength Length of input data, in bytes.
|
||||
* @param pu16DataBytesRead Number Of Data Bytes Read u16IdValue
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (error in arguments)
|
||||
* @retval PDM_E_STATUS_INTERNAL_ERROR
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadPartialDataFromExistingRecord(uint16_t u16IdValue,
|
||||
uint16_t u16TableOffset,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function reads the specified record of application data from the NVM and stores
|
||||
* the read data in the supplied data buffer in RAM. The record is specified using its
|
||||
* unique 16-bit identifier.
|
||||
* Before calling this function, it may be useful to call PDM_bDoesDataExist() in order
|
||||
* to determine whether a record with the specified identifier exists in the EEPROM and,
|
||||
* if it does, to obtain its size.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read
|
||||
* @param pvDataBuffer Pointer to the data buffer in RAM where the read data is to
|
||||
* be stored
|
||||
* @param u16DataBufferLength Length of the data buffer, in bytes
|
||||
* @param pu16DataBytesRead Pointer to a location to receive the number of data bytes
|
||||
* read
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM otherwise i.e. specified record ID is invalid
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadDataFromRecord(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes the specified record of application data in NVM.
|
||||
* @see PDM_eDeleteAllData to alternatively delete all records in NVM
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be deleted
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteDataRecord(uint16_t u16IdValue);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes all records in NVM, including both application data and stack
|
||||
* context data, resulting in an empty PDM file system. The NVM segment Wear Count
|
||||
* values are preserved (and incremented) throughout this function call.
|
||||
* This function is to be used with extreme care in a Zigbee application context
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteAllDataRecords(void);
|
||||
|
||||
/*!
|
||||
* @brief Seeks for a certain record by record identifier
|
||||
*
|
||||
* This function checks whether data associated with thd specified record ID
|
||||
* exists in the NVM. If the data record exists, the function returns the data
|
||||
* length, in bytes, in a location to which a pointer must be provided.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be found
|
||||
* @param pu16DataLength Pointer to location to receive length, in bytes,
|
||||
* of data record (if any) associated with specified record ID
|
||||
*
|
||||
* @retval true if record was fond false otherwise
|
||||
*/
|
||||
PUBLIC bool_t PDM_bDoesDataExist(uint16_t u16IdValue, uint16_t *pu16DataLength);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are left in the PDM space
|
||||
*
|
||||
* This function returns the number of unused segments that remain in the NVM.
|
||||
* Note that the returned parameter being a uint8_t the total expected number of
|
||||
* segments cannot exceed 255
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of PDM NVM segments free
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentCapacity(void);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are occupied in the PDM space
|
||||
*
|
||||
* This function returns the number of used segments in the NVM
|
||||
* @see PDM_u8GetSegmentCapacity
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of NVM segments used
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentOccupancy(void);
|
||||
|
||||
/*!
|
||||
* @brief Register a User defined system callback function
|
||||
*
|
||||
* This function registers a callback function that will be called in error events
|
||||
* @see PDM_pfGetSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param fpvPDM_SystemEventCallback function to replace the one that was set on PDM initialisation
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vRegisterSystemCallback(PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the previously defined system callback function
|
||||
*
|
||||
* This function retrieves the callback function that has been set by PDM_eInitialise
|
||||
* or PDM_vRegisterSystemCallback
|
||||
* @see PDM_vRegisterSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval fpvPDM_SystemEventCallback function used to notify error events
|
||||
*/
|
||||
PUBLIC PDM_tpfvSystemEventCallback PDM_pfGetSystemCallback(void);
|
||||
|
||||
PUBLIC void PDM_vSetWearCountTriggerLevel(uint32_t u32WearCountTriggerLevel);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetSegmentWearCount(uint8_t u8SegmentIndex, uint32_t *pu32WearCount);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetDeviceWearCountProfile(uint32_t au32WearCount[], uint8_t u8NumberOfSegments);
|
||||
|
||||
PUBLIC void PDM_vSetWearLevelDifference(uint32_t u32WearLevelDifference);
|
||||
|
||||
int PDM_Init(void);
|
||||
|
||||
#if defined UART_DEBUG
|
||||
PUBLIC void vPDM_InitialiseDisplayDataInFileSystem(uint16_t *pau16PDMFileIDrecord, uint8_t u8NumberOfPDMSegments);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInFileSystem(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayDataWithIdInFileSystem(uint16_t u16IdValue);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInNVM(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayNVMsegmentData(uint8_t u8SegmentIndex);
|
||||
|
||||
PUBLIC char *psPDM_PrintEventID(PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
PUBLIC int iPDM_ReadRawNVMsegmentDataToBuffer(uint8_t u8SegmentIndex,
|
||||
uint8_t *pu8SegmentDataBuffer,
|
||||
uint16_t *pu16SegmentDataSize);
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
extern PUBLIC const uint32_t PDM_g_u32Version;
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /*PDM_H_INCLUDED*/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** END OF FILE ***/
|
||||
/****************************************************************************/
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE:
|
||||
*
|
||||
* COMPONENT:
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5168, JN5179].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2016. All rights reserved
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "projdefs.h"
|
||||
#include "portable.h"
|
||||
#else
|
||||
#include "MemManager.h"
|
||||
#endif
|
||||
|
||||
#include "FunctionLib.h"
|
||||
#include "fsl_debug_console.h"
|
||||
#include "Flash_Adapter.h"
|
||||
#include "PDM.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t u8Level;
|
||||
} tsMicroIntStorage;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define __WEAK_FUNC __attribute__((weak))
|
||||
#elif defined(__ICCARM__)
|
||||
#define __WEAK_FUNC __weak
|
||||
#elif defined( __CC_ARM )
|
||||
#define __WEAK_FUNC __weak
|
||||
#endif
|
||||
|
||||
#if gUsePdm_d
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
/* In this module pvHeap_Alloc, vHeap_Free, vHeap_ResetHeap,
|
||||
* vMicroIntEnableOnly, vMicroIntRestoreState
|
||||
* are default weak implementations that can be overridden
|
||||
* for USE_RTOS or DUAL_MODE_APP builds */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Local Function Prototypes ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Local Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Imported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_HEAP_ALLOC = 0,
|
||||
E_HEAP_RESET,
|
||||
E_FUNCTION_MAX
|
||||
} eFunctionId;
|
||||
|
||||
|
||||
|
||||
/* Nested interrupt control */
|
||||
#ifndef MICRO_SET_PRIMASK_LEVEL
|
||||
#define MICRO_SET_PRIMASK_LEVEL(A) __set_PRIMASK(A)
|
||||
#endif
|
||||
// read back PRIMASK status into u32Store variable then disable the interrupts
|
||||
#ifndef MICRO_DISABLE_AND_SAVE_INTERRUPTS
|
||||
#define MICRO_DISABLE_AND_SAVE_INTERRUPTS(u32Store) \
|
||||
u32Store = __get_PRIMASK(); __disable_irq();
|
||||
#endif
|
||||
#ifndef MICRO_GET_ACTIVE_INT_LEVEL
|
||||
#define MICRO_GET_ACTIVE_INT_LEVEL __get_BASEPRI
|
||||
#endif
|
||||
#ifndef MICRO_SET_ACTIVE_INT_LEVEL_MAX
|
||||
#define MICRO_SET_ACTIVE_INT_LEVEL_MAX(A) __set_BASEPRI_MAX(A)
|
||||
#endif
|
||||
#ifndef MICRO_SET_ACTIVE_INT_LEVEL
|
||||
#define MICRO_SET_ACTIVE_INT_LEVEL(A) __set_BASEPRI(A)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: pvHeap_Alloc
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Allocates a block of memory from the heap.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to block, or NULL if the heap didn't have enough space. If block
|
||||
* was already assigned, returns original value and doesn't take anything
|
||||
* from heap.
|
||||
*
|
||||
* NOTES:
|
||||
* If buffer has already been allocated, it is not cleared.
|
||||
* If it is a fresh allocation, it is cleared on request.
|
||||
*
|
||||
****************************************************************************/
|
||||
__WEAK_FUNC void *pvHeap_Alloc(void *pvPointer, uint32_t u32BytesNeeded, bool_t bClear)
|
||||
{
|
||||
do {
|
||||
if (pvPointer != NULL) break;
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
pvPointer = pvPortMalloc(u32BytesNeeded);
|
||||
#else
|
||||
pvPointer = MEM_BufferAllocWithId(u32BytesNeeded, gPdmMemPoolId_c, (void*)__get_LR());
|
||||
#endif
|
||||
if (pvPointer == NULL) break;
|
||||
if (bClear)
|
||||
{
|
||||
FLib_MemSet(pvPointer, 0, u32BytesNeeded);
|
||||
}
|
||||
} while (0);
|
||||
return pvPointer;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: vHeap_Free
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Release a block of memory from the heap.
|
||||
*
|
||||
* RETURNS:
|
||||
* none
|
||||
* NOTES:
|
||||
*
|
||||
****************************************************************************/
|
||||
__WEAK_FUNC void vHeap_Free(void *pvPointer)
|
||||
{
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
vPortFree(pvPointer);
|
||||
#else
|
||||
memStatus_t status;
|
||||
status = MEM_BufferFree(pvPointer);
|
||||
if (status != MEM_SUCCESS_c)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRINTF("MemMngt error freeing %08lx code=%d\r\n", (uint32_t)pvPointer, status);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__WEAK_FUNC void vHeap_ResetHeap(void)
|
||||
{
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__WEAK_FUNC void vMicroIntEnableOnly(tsMicroIntStorage *int_storage, uint32_t u32EnableMask)
|
||||
{
|
||||
uint32_t primask_lvl;
|
||||
MICRO_DISABLE_AND_SAVE_INTERRUPTS(primask_lvl);
|
||||
int_storage->u8Level = (uint8_t)MICRO_GET_ACTIVE_INT_LEVEL();
|
||||
MICRO_SET_ACTIVE_INT_LEVEL_MAX( 96 );
|
||||
MICRO_SET_PRIMASK_LEVEL(primask_lvl);
|
||||
}
|
||||
|
||||
__WEAK_FUNC void vMicroIntRestoreState(tsMicroIntStorage * int_storage)
|
||||
{
|
||||
MICRO_SET_ACTIVE_INT_LEVEL(int_storage->u8Level);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: PDM_Init
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Wrapper to call PDM Initialization with the right Flash configuration parameters
|
||||
*
|
||||
* Note: FLASH_Init must have been called beforehand in order to initialize gFlashConfig.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0: if no error, negative value otherwise
|
||||
* NOTES:
|
||||
*
|
||||
****************************************************************************/
|
||||
int PDM_Init(void)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
#if gUsePdm_d
|
||||
static bool pdm_init_done = false;
|
||||
|
||||
do {
|
||||
if (pdm_init_done)
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
NV_Init(); /* used to setup the gFlashConfig.PFlashTotalSize value */
|
||||
|
||||
PDM_teStatus st = PDM_E_STATUS_INTERNAL_ERROR;
|
||||
uint8_t *base = (uint8_t*)NV_STORAGE_END_ADDRESS;
|
||||
size_t len = (size_t)((uint32_t)NV_STORAGE_START_ADDRESS + 1 - (uint32_t)NV_STORAGE_END_ADDRESS);
|
||||
#ifdef DEBUG
|
||||
uint8_t * flash_top = (uint8_t*)(gFlashConfig.PFlashTotalSize + gFlashConfig.PFlashBlockBase);
|
||||
uint8_t * flash_base = (uint8_t*)gFlashConfig.PFlashBlockBase;
|
||||
assert(base >= flash_base);
|
||||
assert(base + len <= flash_top);
|
||||
assert(len > FLASH_PAGE_SIZE*2);
|
||||
#endif
|
||||
#if !defined gPdmNbSegments || (gPdmNbSegments < NV_STORAGE_MAX_SECTORS)
|
||||
#error "gPdmNbSegments should match NV_STORAGE_MAX_SECTORS"
|
||||
#endif
|
||||
uint32_t sect_sz_log = Flib_Log2(gFlashConfig.PFlashSectorSize);
|
||||
st = PDM_eInitialise(ADDR2SEG(base, sect_sz_log),
|
||||
SIZE2SEGNB(len, sect_sz_log), NULL);
|
||||
|
||||
if (st != PDM_E_STATUS_OK)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRINTF("PDM/NVM misconfiguration\r\n");
|
||||
#endif
|
||||
assert(st != PDM_E_STATUS_OK);
|
||||
status = -st;
|
||||
break;
|
||||
}
|
||||
pdm_init_done = true;
|
||||
status = 0;
|
||||
} while (0);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the Panic module.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef __PANIC_H__
|
||||
#define __PANIC_H__
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
typedef uint32_t panicId_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
panicId_t id;
|
||||
uint32_t location;
|
||||
uint32_t extra1;
|
||||
uint32_t extra2;
|
||||
uint32_t linkRegister;
|
||||
uint32_t cpsr_contents; /* may not be used initially */
|
||||
uint8_t stack_dump[4]; /* initially just contain the contents of the LR */
|
||||
} panicData_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifndef gUsePanic_c
|
||||
#define gUsePanic_c 0
|
||||
#endif
|
||||
|
||||
#define ID_PANIC(grp,value) ((panicId_t)(((panicId_t)(grp) << 16)+((panicId_t)(value))))
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void panic
|
||||
(
|
||||
panicId_t id,
|
||||
uint32_t location,
|
||||
uint32_t extra1,
|
||||
uint32_t extra2
|
||||
);
|
||||
|
||||
#endif /* __PANIC_H__ */
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the Panic module.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#include "Panic.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#if gLoggingActive_d
|
||||
#include "dbg_logging.h"
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if gUsePanic_c
|
||||
panicData_t panic_data;
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function will halt the system
|
||||
*
|
||||
* \param[in] id Description of the param2 in parameter
|
||||
* \param[in] location address where the Panic occurred
|
||||
* \param[in] extra1 parameter to be stored in Panic structure
|
||||
* \param[in] extra2 parameter to be stored in Panic structure
|
||||
*
|
||||
********************************************************************************** */
|
||||
|
||||
void panic( panicId_t id, uint32_t location, uint32_t extra1, uint32_t extra2 )
|
||||
{
|
||||
#if gUsePanic_c
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = 0;
|
||||
__asm("push {r2} ");
|
||||
__asm("push {LR} ");
|
||||
__asm("pop {r2} ");
|
||||
#if defined(__GNUC__)
|
||||
__asm("str r2, [SP, #24]");
|
||||
#else
|
||||
__asm("str r2, [SP, #4]");
|
||||
#endif
|
||||
__asm("pop {r2}");
|
||||
|
||||
panic_data.id = id;
|
||||
panic_data.location = location;
|
||||
panic_data.extra1 = extra1;
|
||||
panic_data.extra2 = extra2;
|
||||
panic_data.linkRegister = savedLR;
|
||||
panic_data.cpsr_contents = 0;
|
||||
|
||||
OSA_InterruptDisable(); /* disable interrupts */
|
||||
#if gLoggingActive_d
|
||||
DbgLogDump(1);
|
||||
#endif
|
||||
/* infinite loop just to ensure this routine never returns */
|
||||
for(;;)
|
||||
{
|
||||
__asm("NOP");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
void __attribute__((weak)) __assertion_failed(char* s) {}
|
||||
#endif
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* MCU reset related functions implementation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
#include "fsl_device_registers.h"
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
#include "fsl_reset.h"
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
void ResetMCU(void);
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
void ResetMCU(void)
|
||||
{
|
||||
#ifdef CPU_JN518X
|
||||
RESET_SystemReset();
|
||||
#else
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
while(1){}
|
||||
}
|
||||
|
||||
/********************************** EOF ***************************************/
|
||||
Vendored
Executable
+822
@@ -0,0 +1,822 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "Flash_Adapter.h"
|
||||
#include "FunctionLib.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#if gNvStorageIncluded_d
|
||||
#include "NVM_Interface.h"
|
||||
#endif
|
||||
#include "Panic.h"
|
||||
#include "fsl_debug_console.h"
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
* Private macros
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
#if (PGM_SIZE_BYTE == 4)
|
||||
#define mProgBuffSizeInPgmWrUnits_c 16
|
||||
#elif (PGM_SIZE_BYTE == 8)
|
||||
#define mProgBuffSizeInPgmWrUnits_c 8
|
||||
#else
|
||||
#define mProgBuffSizeInPgmWrUnits_c 4
|
||||
#endif
|
||||
|
||||
/* Generator for CRC calculations. */
|
||||
#define POLGEN 0x1021
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
#include "rom_psector.h"
|
||||
void ResetMCU(void);
|
||||
#endif
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
static uint32_t NV_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t* pData);
|
||||
#if !defined CPU_QN908X && ! defined CPU_JN518X
|
||||
static uint8_t NV_VerifyCrcOverHWParameters(hardwareParameters_t* pHwParams);
|
||||
static uint16_t NV_ComputeCrcOverHWParameters(hardwareParameters_t* pHwParams);
|
||||
#endif
|
||||
static void NV_Flash_WaitForCSEndAndDisableInterrupts(void);
|
||||
#ifdef CPU_QN908X
|
||||
static uint32_t SwFlashVerifyErase (uint32_t start, uint32_t lengthInBytes);
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/* Hardware parameters */
|
||||
hardwareParameters_t gHardwareParameters;
|
||||
extern flash_config_t gFlashConfig;
|
||||
|
||||
|
||||
#if !defined CPU_QN908X && !defined CPU_JN518X
|
||||
static const uint8_t mProdDataIdentifier[10] = {"PROD_DATA:"};
|
||||
#endif
|
||||
#if (USE_RTOS)
|
||||
static osaSemaphoreId_t mFlashAdapterSemaphoreId;
|
||||
#endif
|
||||
static volatile uint8_t mFA_CSFlag = 0;
|
||||
static volatile uint8_t mFA_SemWaitCount = 0;
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
* Private functions
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
/*! *********************************************************************************
|
||||
* \brief This function ensures that there are no critical sections on and disables interrupts.
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
static void NV_Flash_WaitForCSEndAndDisableInterrupts(void)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
#if (gNvStorageIncluded_d)
|
||||
/*on freeRTOS NvIdle runs on a freeRTOS idle task hook which must never block. In this RTOS at least one task must be ready */
|
||||
/*since NvIdle runs on the task which has the least priority in the system we can wait in a loop for the end of the critical section */
|
||||
osaTaskId_t currentTaskId = OSA_TaskGetId();
|
||||
if(currentTaskId == (osaTaskId_t)NvGetNvIdleTaskId())
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
while (mFA_CSFlag);
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mFA_SemWaitCount++;
|
||||
OSA_InterruptEnable();
|
||||
OSA_SemaphoreWait(mFlashAdapterSemaphoreId, osaWaitForever_c);
|
||||
}
|
||||
}
|
||||
#else
|
||||
OSA_InterruptDisable();
|
||||
#endif
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Write aligned data to FLASH
|
||||
*
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint32_t NV_FlashProgramAdaptation(uint32_t dest, uint32_t size, uint8_t* pData)
|
||||
{
|
||||
uint32_t progBuf[PGM_SIZE_BYTE/sizeof(uint32_t)];
|
||||
uint32_t status = kStatus_FLASH_Success;
|
||||
#if !defined (CPU_JN518X)
|
||||
if( (size & (PGM_SIZE_BYTE - 0x01U)) != 0 )
|
||||
{
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
#if gFlashEraseDuringWrite
|
||||
{
|
||||
NV_FlashEraseSector(dest, size-1);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if( (size & (PGM_SIZE_BYTE - 0x01U)) != 0 )
|
||||
{
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
if( (dest & MASK_LOG(PGM_SIZE_BYTE_LOG)) != 0 )
|
||||
{
|
||||
PRINTF("Unaligned flash address %08lx", dest);
|
||||
return kStatus_FLASH_AlignmentError;
|
||||
}
|
||||
|
||||
NV_FlashEraseSector(dest, size-1);
|
||||
#endif
|
||||
|
||||
|
||||
while(size)
|
||||
{
|
||||
FLib_MemCpy(progBuf, pData, PGM_SIZE_BYTE);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
status = FLASH_PROGRAM_AREA(dest, progBuf, PGM_SIZE_BYTE);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
|
||||
if(status != kStatus_FLASH_Success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pData += PGM_SIZE_BYTE;
|
||||
dest += PGM_SIZE_BYTE;
|
||||
size -= PGM_SIZE_BYTE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined CPU_QN908X && ! defined CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief Verifies if the CRC field matches computed CRC over stored values
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return 1 on success, 0 otherwise
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint8_t NV_VerifyCrcOverHWParameters(hardwareParameters_t* pHwParams)
|
||||
{
|
||||
uint8_t status = 0;
|
||||
|
||||
if(NV_ComputeCrcOverHWParameters(pHwParams) == pHwParams->hardwareParamsCrc)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Computes the CRC for the hardware parameters and stores it
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return Computed CRC value.
|
||||
*
|
||||
********************************************************************************** */
|
||||
static uint16_t NV_ComputeCrcOverHWParameters(hardwareParameters_t* pHwParams)
|
||||
{
|
||||
uint16_t computedCRC = 0;
|
||||
uint8_t crcA;
|
||||
uint8_t byte = 0;
|
||||
if(NULL != pHwParams)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)(&pHwParams->reserved);
|
||||
uint16_t len = (uint8_t *)(&pHwParams->hardwareParamsCrc) -
|
||||
(uint8_t *)(&pHwParams->reserved);
|
||||
while(len)
|
||||
{
|
||||
byte = *ptr;
|
||||
computedCRC ^= ((uint16_t)byte << 8);
|
||||
for(crcA = 8; crcA; crcA--)
|
||||
{
|
||||
if(computedCRC & 0x8000) {
|
||||
computedCRC <<= 1;
|
||||
computedCRC ^= POLGEN;
|
||||
}
|
||||
else computedCRC <<= 1;
|
||||
}
|
||||
--len;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return computedCRC;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPU_QN908X
|
||||
/*! *********************************************************************************
|
||||
* \brief Flash verify erase software implementation
|
||||
*
|
||||
* \param[in] start - start address of the memory block to be verified
|
||||
* \param[in] lengthInBytes - memory block length
|
||||
*
|
||||
* \return TRUE if the flash memory area is blank (erased), FALSE otherwise
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t SwFlashVerifyErase (uint32_t start, uint32_t lengthInBytes)
|
||||
{
|
||||
uint8_t* pAddress = (uint8_t*)start;
|
||||
flash_status_t status = kStatus_FLASH_Success;
|
||||
|
||||
do
|
||||
{
|
||||
if(*pAddress++ != 0xff)
|
||||
{
|
||||
status = kStatus_FLASH_EraseError;
|
||||
break;
|
||||
}
|
||||
} while(--lengthInBytes);
|
||||
|
||||
return (uint32_t)status;
|
||||
}
|
||||
#endif
|
||||
#ifdef CPU_JN518X
|
||||
#define FLASH_WORD_SZ 16
|
||||
|
||||
/* This is kept as an example of code using the TRY .. CATCH for exceptions
|
||||
* Using it raises some execution issues with a debugger
|
||||
*/
|
||||
uint32_t NV_ReadSweep(uint32_t start_addr, uint32_t end_addr)
|
||||
{
|
||||
uint32_t addr = start_addr;
|
||||
TRY
|
||||
{
|
||||
while (addr < end_addr)
|
||||
{
|
||||
volatile uint32_t read_val;
|
||||
read_val = *(uint32_t*)addr;
|
||||
read_val = read_val;
|
||||
addr += FLASH_WORD_SZ;
|
||||
}
|
||||
}
|
||||
CATCH (BUS_EXCEPTION)
|
||||
{
|
||||
/* return page address if an error is detected */
|
||||
return ROUND_FLOOR(addr, 9);
|
||||
}
|
||||
YRT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t NV_SafeReadFromFlash(uint8_t * ram_dst, uint8_t * flash_src, size_t size)
|
||||
{
|
||||
uint32_t au32Data[FLASH_WORD_SZ/sizeof(uint32_t)];
|
||||
uint32_t st = kStatus_FLASH_Fail;
|
||||
uint32_t nb_flash_words = (size + (FLASH_WORD_SZ-1)) / FLASH_WORD_SZ;
|
||||
while (nb_flash_words-- > 0)
|
||||
{
|
||||
size_t sz;
|
||||
sz = (size >= FLASH_WORD_SZ) ? FLASH_WORD_SZ : size;
|
||||
st = FLASH_Read(FLASH, flash_src, 0, au32Data);
|
||||
if (st != kStatus_FLASH_Success) break;
|
||||
memcpy(ram_dst, (uint8_t*)&au32Data[0], sz);
|
||||
ram_dst += sz;
|
||||
flash_src += sz;
|
||||
size -= sz;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
void NV_FlashPerformAudit(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
uint32_t addr = INT_STORAGE_START_OFFSET;
|
||||
if (INT_STORAGE_END_OFFSET == INT_STORAGE_START_OFFSET) addr++;
|
||||
uint32_t end = (uint32_t)0x9ddff;
|
||||
|
||||
uint32_t failed_addr;
|
||||
uint8_t buf[FLASH_PAGE_SIZE];
|
||||
|
||||
while (addr <= ROUND_FLOOR(end, 9))
|
||||
{
|
||||
status = FLASH_BlankCheck(FLASH, (uint8_t*)addr, (uint8_t*)end);
|
||||
if (kStatus_FLASH_Fail == status)
|
||||
{
|
||||
failed_addr = FLASH->DATAW[0]; /* is a flash word address */
|
||||
failed_addr <<= 4;
|
||||
addr = ROUND_FLOOR(failed_addr, 9);
|
||||
status = NV_SafeReadFromFlash(buf, (uint8_t*)addr, FLASH_PAGE_SIZE);
|
||||
if (kStatus_FLASH_Success != status)
|
||||
{
|
||||
status = FLASH_Erase(FLASH,
|
||||
(uint8_t*)addr,
|
||||
(uint8_t*)(addr+FLASH_PAGE_SIZE-1));
|
||||
if (status != kStatus_FLASH_Success)
|
||||
{
|
||||
PRINTF("NV Audit Erase failed at addr=%08lx\r\n", addr);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
addr += FLASH_PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifdef CPU_JN518X
|
||||
int PsectorUpdateFlashAudit(uint32_t new_value)
|
||||
{
|
||||
int res = 1;
|
||||
psector_page_data_t page_buf;
|
||||
psector_page_data_t *page0 = (psector_page_data_t*)0x9e800;
|
||||
|
||||
memcpy(&page_buf, page0, FLASH_PAGE_SIZE);
|
||||
|
||||
((psector_page_data_t*)&page_buf)->page0_v3.flash_audit_done = new_value;
|
||||
page_buf.hdr.version ++;
|
||||
page_buf.hdr.checksum = psector_CalculateChecksum((psector_page_t *)&page_buf);
|
||||
if (psector_WriteUpdatePage(PSECTOR_PAGE0_PART, (psector_page_t *)&page_buf) != WRITE_OK)
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetMCU(); /* Commit now by forcing reset */
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int psector_FlashAudit(void)
|
||||
{
|
||||
int res = -1;
|
||||
do {
|
||||
psector_page_data_t *page0 = (psector_page_data_t*)0x9e800;
|
||||
uint32_t flash_audit_word = page0->page0_v3.flash_audit_done;
|
||||
|
||||
if ((flash_audit_word & 0xffff) == FLASH_AUDIT_DONE)
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to verify internal flash */
|
||||
NV_FlashPerformAudit();
|
||||
uint32_t flash_audit_code = (flash_audit_word & 0xffff0000u) | FLASH_AUDIT_DONE;
|
||||
res = PsectorUpdateFlashAudit(flash_audit_code);
|
||||
if (res < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Initialize the FLASH driver
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Init(void)
|
||||
{
|
||||
static bool_t nvmInit = 0;
|
||||
if(nvmInit == 0)
|
||||
{
|
||||
#ifdef CPU_QN908X
|
||||
/* Configure Flash */
|
||||
FLASH_GetDefaultConfig(&gFlashConfig);
|
||||
gFlashConfig.blockBase = 0x0U;
|
||||
#endif /* CPU_QN908X */
|
||||
#ifdef gNVM_MULTICORE_SUPPORT_d
|
||||
FLASH_SetProperty(&gFlashConfig, kFLASH_PropertyFlashMemoryIndex, 1);
|
||||
#endif
|
||||
/* Init Flash */
|
||||
FLASH_INIT();
|
||||
#if (defined(CPU_MKW36Z512VFP4) || defined(CPU_MKW36Z512VHT4))
|
||||
/* KW36 has 256KB of FlexNVM mapped at adress 0x1000 0000 which also has an alias starting from address 0x0004 0000.
|
||||
* Configured the Flash driver to treat the PFLASH bloxk and FlexNVM block as a continuous memory block. */
|
||||
gFlashConfig.DFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE * FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT;
|
||||
#endif
|
||||
#if (USE_RTOS)
|
||||
if( (mFlashAdapterSemaphoreId = OSA_SemaphoreCreate(0)) == NULL )
|
||||
{
|
||||
panic( ID_PANIC(0,0), (uint32_t)NV_Init, 0, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
if (!nvmInit)
|
||||
{
|
||||
if (psector_FlashAudit() == 0)
|
||||
nvmInit = 1;
|
||||
}
|
||||
#else
|
||||
nvmInit = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* Name: NvSetCriticalSection
|
||||
* Description: enter critical section
|
||||
* Parameters: -
|
||||
* Return: -
|
||||
******************************************************************************/
|
||||
/*! *********************************************************************************
|
||||
* \brief Start a critical section during which flash operations are not allowed
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Flash_SetCriticalSection
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
OSA_InterruptDisable();
|
||||
++mFA_CSFlag;
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Start a critical section during which flash operations are not allowed
|
||||
*
|
||||
* \param[in] none
|
||||
* \return nothing
|
||||
*
|
||||
********************************************************************************** */
|
||||
void NV_Flash_ClearCriticalSection
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
#if (USE_RTOS)
|
||||
OSA_InterruptDisable();
|
||||
if(mFA_CSFlag)
|
||||
{
|
||||
mFA_CSFlag--;
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
while(1)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if(mFA_CSFlag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(mFA_SemWaitCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mFA_SemWaitCount--;
|
||||
OSA_InterruptEnable();
|
||||
OSA_SemaphorePost(mFlashAdapterSemaphoreId);
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Verify erase data in Flash
|
||||
*
|
||||
* \param[in] start The address of the Flash location
|
||||
* \param[in] lengthInBytes The number of bytes to be checked
|
||||
* \param[in] margin
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashVerifyErase ( uint32_t start, uint32_t lengthInBytes)
|
||||
{
|
||||
uint32_t status;
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
|
||||
status = FLASH_VERIFY_ERASE(start, lengthInBytes);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Write aligned data to FLASH
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashProgram(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData)
|
||||
{
|
||||
return NV_FlashProgramAdaptation(dest, size, pData);
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Write data to FLASH
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The address of the Flash location
|
||||
* \param[in] size The number of bytes to be programed
|
||||
* \param[in] pData Pointer to the data to be programmed to Flash
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashProgramUnaligned(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData)
|
||||
{
|
||||
uint8_t buffer[PGM_SIZE_BYTE];
|
||||
uint32_t status;
|
||||
do {
|
||||
uint32_t align_addr = ROUND_FLOOR(dest, PGM_SIZE_BYTE_LOG);
|
||||
uint16_t bytes = (dest - align_addr);
|
||||
|
||||
if( bytes )
|
||||
{
|
||||
uint16_t unalignedBytes = PGM_SIZE_BYTE - bytes;
|
||||
|
||||
if( unalignedBytes > size )
|
||||
{
|
||||
unalignedBytes = size;
|
||||
}
|
||||
|
||||
if (FLib_CopyFromFlash(buffer, (void*)align_addr, PGM_SIZE_BYTE))
|
||||
{
|
||||
PRINTF("Raised error while reading from %08lx\r\n", align_addr);
|
||||
}
|
||||
|
||||
|
||||
FLib_MemCpy(&buffer[bytes], pData, unalignedBytes);
|
||||
|
||||
status = NV_FlashProgramAdaptation(align_addr, PGM_SIZE_BYTE, buffer);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
|
||||
dest += unalignedBytes;
|
||||
/* if size is less than the distance to the end of program block
|
||||
unalignedBytes has been shrunk , after size is decremented it will become 0 */
|
||||
pData += unalignedBytes;
|
||||
size -= unalignedBytes;
|
||||
}
|
||||
|
||||
bytes = size & ~(PGM_SIZE_BYTE - 1U);
|
||||
|
||||
/* Now dest is on an aligned boundary */
|
||||
/* bytes is an integer number of program blocks (pages) */
|
||||
if( bytes )
|
||||
{
|
||||
status = NV_FlashProgramAdaptation(dest, bytes, pData);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
|
||||
dest += bytes;
|
||||
pData += bytes;
|
||||
size -= bytes;
|
||||
}
|
||||
|
||||
/* dest is still aligned because we have increased it by a multiple of the program block (page) */
|
||||
if( size )
|
||||
{
|
||||
if (
|
||||
#ifdef CPU_JN518X
|
||||
/* Avoid reading page if it is blank */
|
||||
(FLASH_VERIFY_ERASE(dest, PGM_SIZE_BYTE) == kStatus_FLASH_Fail) &&
|
||||
#endif
|
||||
(FLib_CopyFromFlash(buffer, (void*)dest, PGM_SIZE_BYTE))
|
||||
)
|
||||
{
|
||||
PRINTF("Raised error while reading from %08lx\r\n", (dest - bytes));
|
||||
}
|
||||
|
||||
FLib_MemCpy(buffer, pData, size);
|
||||
status = NV_FlashProgramAdaptation(dest, PGM_SIZE_BYTE, buffer);
|
||||
|
||||
if(status != kStatus_FLASH_Success) break;
|
||||
}
|
||||
status = kStatus_FLASH_Success;
|
||||
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Erase to 0xFF one ore more FLASH sectors.
|
||||
*
|
||||
* \param[in] pSSDConfig Pointer to a flash config structure
|
||||
* \param[in] dest The start address of the first sector to be erased
|
||||
* \param[in] size The amount of flash to be erased (multiple of sector size)
|
||||
* \param[in] pFlashCommandSequence Pointer to the Flash RAM function
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_FlashEraseSector(uint32_t dest, uint32_t size)
|
||||
{
|
||||
uint32_t status;
|
||||
#ifdef CPU_QN908X
|
||||
uint32_t status_flags;
|
||||
#endif
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
NV_Flash_WaitForCSEndAndDisableInterrupts();
|
||||
#endif
|
||||
#if defined(CPU_QN908X)
|
||||
status_flags = FLASH_GetStatusFlags();
|
||||
if(status_flags & FLASH_INT_STAT_AHBL_INT_MASK)
|
||||
{
|
||||
FLASH_ClearStatusFlags(FLASH_INTCLR_AHBL_INTCLR_MASK);
|
||||
}
|
||||
if(status_flags & FLASH_INT_STAT_AHBH_INT_MASK)
|
||||
{
|
||||
FLASH_ClearStatusFlags(FLASH_INTCLR_AHBH_INTCLR_MASK);
|
||||
}
|
||||
#endif
|
||||
status = FLASH_ERASE_AREA(dest, size);
|
||||
|
||||
#if gNvDisableIntCmdSeq_c
|
||||
OSA_InterruptEnable();
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined CPU_QN908X && !defined CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief Load the HW parameters from Flash to RAM
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure where HW parameters will be stored
|
||||
*
|
||||
* \return error code
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_ReadHWParameters(hardwareParameters_t *pHwParams)
|
||||
{
|
||||
hardwareParameters_t* pLocalParams = (hardwareParameters_t*)FREESCALE_PROD_DATA_BASE_ADDR;
|
||||
uint32_t status = 0;
|
||||
do {
|
||||
|
||||
if(NULL == pHwParams)
|
||||
{
|
||||
/* Invalid parameter */
|
||||
status = 2;
|
||||
break;
|
||||
}
|
||||
#ifdef CPU_JN518X
|
||||
#if 0
|
||||
if (NV_SafeReadFromFlash((uint8_t*)pHwParams,
|
||||
(uint8_t*)pLocalParams,
|
||||
sizeof(hardwareParameters_t)) == kStatus_FLASH_Success)
|
||||
{
|
||||
if (FLib_MemCmp(pHwParams,
|
||||
(void*)mProdDataIdentifier,
|
||||
sizeof(mProdDataIdentifier)) &&
|
||||
NV_VerifyCrcOverHWParameters(pHwParams))
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NV_FlashEraseSector((uint32_t)pLocalParams, FLASH_PAGE_SIZE-1);
|
||||
FLib_MemSet(pHwParams, 0xFF, sizeof(hardwareParameters_t));
|
||||
status = 1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (FLib_MemCmp(FREESCALE_PROD_DATA_BASE_ADDR, (void*)mProdDataIdentifier, sizeof(mProdDataIdentifier)) &&
|
||||
NV_VerifyCrcOverHWParameters(pLocalParams))
|
||||
{
|
||||
FLib_MemCpy(pHwParams, FREESCALE_PROD_DATA_BASE_ADDR, sizeof(hardwareParameters_t));
|
||||
status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FLib_MemSet(pHwParams, 0xFF, sizeof(hardwareParameters_t));
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
/*! *********************************************************************************
|
||||
* \brief Store the HW parameters to Flash
|
||||
*
|
||||
* \param[in] pHwParams pointer to a structure containing HW parameters
|
||||
*
|
||||
* \return error code of the Flash erase/write functions
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t NV_WriteHWParameters(hardwareParameters_t *pHwParams)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
NV_Init();
|
||||
|
||||
#ifndef CPU_JN518X
|
||||
#ifdef CPU_JN518X
|
||||
|
||||
status = FLASH_BlankCheck(FLASH, (uint8_t *)FREESCALE_PROD_DATA_BASE_ADDR,
|
||||
(uint8_t *)(FREESCALE_PROD_DATA_BASE_ADDR + sizeof(hardwareParameters_t)));
|
||||
#endif
|
||||
|
||||
if(
|
||||
#ifdef CPU_JN518X
|
||||
(status == kStatus_FLASH_Success) ||
|
||||
#endif
|
||||
!FLib_MemCmp(pHwParams, (void*)FREESCALE_PROD_DATA_BASE_ADDR, sizeof(hardwareParameters_t)))
|
||||
{
|
||||
pHwParams->hardwareParamsCrc = NV_ComputeCrcOverHWParameters(pHwParams);
|
||||
FLib_MemCpy(pHwParams->identificationWord, (void*)mProdDataIdentifier, sizeof(mProdDataIdentifier));
|
||||
|
||||
#if defined(FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE)
|
||||
status = NV_FlashEraseSector((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
|
||||
#elif defined(FSL_FEATURE_FLASH_PAGE_SIZE_BYTES)
|
||||
status = NV_FlashEraseSector((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR, FSL_FEATURE_FLASH_PAGE_SIZE_BYTES);
|
||||
#endif
|
||||
|
||||
if( kStatus_FLASH_Success == status )
|
||||
{
|
||||
status = NV_FlashProgramUnaligned((uint32_t)FREESCALE_PROD_DATA_BASE_ADDR,
|
||||
sizeof(hardwareParameters_t),
|
||||
(uint8_t*)pHwParams);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
#endif /* neither CPU_QN908X not CPU_JN518X */
|
||||
Vendored
Executable
+238
@@ -0,0 +1,238 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017, 2019 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef __FLASH_ADAPTER_H__
|
||||
#define __FLASH_ADAPTER_H__
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_flash.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*
|
||||
* Name: gNvDisableIntCmdSeq_c
|
||||
* Description: this macro is used to enable/disable interrupts when the
|
||||
* FTFL controller executes a command sequence. This macro
|
||||
* has to be set according to NVM configuration. Therefore,
|
||||
* if the FLASH region used by the NVM is placed in the same
|
||||
* program block as the ISR's executable code, the interrupts
|
||||
* MUST be disabled (because no code pre-fetching can be performed
|
||||
* while FTFL controller executes a command sequence, i.e.
|
||||
* program/erase). If the interrupts are not disabled, the
|
||||
* system will assert a hard fault when the flash controller
|
||||
* executes a command sequnce and an IRQ is about to be handled.
|
||||
* If the NVM region is placed in a different program block than
|
||||
* the ISR's code, this macro shall be set to FALSE (recommended).
|
||||
*/
|
||||
#ifndef gNvDisableIntCmdSeq_c
|
||||
#define gNvDisableIntCmdSeq_c (1)
|
||||
#endif
|
||||
|
||||
/* size of array to copy__Launch_Command function to.*/
|
||||
/* It should be at least equal to actual size of __Launch_Command func */
|
||||
/* User can change this value based on RAM size availability and actual size of __Launch_Command function */
|
||||
#define LAUNCH_CMD_SIZE 64
|
||||
#define PGM_SIZE_BYTE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE
|
||||
#define P_BLOCK_NUM FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT
|
||||
#define P_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
|
||||
/* Data Flash block information */
|
||||
#define FLEXNVM_BASE FSL_FEATURE_FLASH_FLEX_NVM_START_ADDRESS
|
||||
#define FLEXNVM_SECTOR_SIZE FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE
|
||||
#define FLEXNVM_BLOCK_SIZE FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SIZE
|
||||
#define FLEXNVM_BLOCK_NUM FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT
|
||||
/* Other defines */
|
||||
#define DEBUGENABLE 0x00
|
||||
#define FTFx_REG_BASE 0x40020000
|
||||
#define P_FLASH_BASE 0x00000000
|
||||
|
||||
/* Flex Ram block information */
|
||||
#define EERAM_BASE FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS
|
||||
#define EERAM_SIZE FSL_FEATURE_FLASH_FLEX_RAM_SIZE
|
||||
|
||||
#define READ_NORMAL_MARGIN 0x00
|
||||
#define READ_USER_MARGIN 0x01
|
||||
#define READ_FACTORY_MARGIN 0x02
|
||||
|
||||
|
||||
|
||||
#define NV_FlashRead(pSrc, pDest, size) FLib_MemCpy((void*)(pDest), (void*)(pSrc), size);
|
||||
|
||||
#if defined(CPU_QN908X)
|
||||
#define kStatus_FLASH_AlignmentError MAKE_STATUS(kStatusGroup_FLASH, 6)
|
||||
#elif defined(CPU_JN518X)
|
||||
|
||||
#define FLASH_AUDIT_DONE 0xc65c
|
||||
int PsectorUpdateFlashAudit(uint32_t new_value);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define PGM_SIZE_BYTE_LOG LOG(PGM_SIZE_BYTE)
|
||||
#define FLASH_PAGE_SZ_LOG LOG(FLASH_PAGE_SIZE)
|
||||
#define IS_MULTIPLE_OF_SECT_SIZE(len) (((len) & (FLASH_PAGE_SIZE-1)) == 0)
|
||||
#define SIZE2SEGNB(sz, sz_log) ((sz)>>(sz_log))
|
||||
#define ADDR2SEG(addr, sz_log) (((uint32_t)(addr))>>(sz_log))
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
extern uint32_t Image$$INT_STORAGE$$Base[];
|
||||
extern uint32_t Image$$INT_STORAGE$$Length[];
|
||||
extern uint32_t Image$$INT_STORAGE$$End[];
|
||||
|
||||
#define INT_STORAGE_START_OFFSET ((uint32_t)Image$$INT_STORAGE$$Base)
|
||||
#define INT_STORAGE_TOTAL_SIZE ((uint32_t)Image$$INT_STORAGE$$Length)
|
||||
#define INT_STORAGE_END_OFFSET ((uint32_t)Image$$INT_STORAGE$$End)
|
||||
|
||||
#else /* defined(__CC_ARM) */
|
||||
extern uint32_t INT_STORAGE_START[];
|
||||
extern uint32_t INT_STORAGE_SIZE[];
|
||||
extern uint32_t INT_STORAGE_END[];
|
||||
extern uint32_t INT_STORAGE_SECTOR_SIZE[];
|
||||
#define INT_STORAGE_START_OFFSET ((uint32_t)INT_STORAGE_END)
|
||||
#define INT_STORAGE_END_OFFSET ((uint32_t)INT_STORAGE_START)
|
||||
#define INT_STORAGE_TOTAL_SIZE ((uint32_t)INT_STORAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_END_ADDRESS
|
||||
* Description: NV_STORAGE_END_ADDRESS from linker command file is used by this code
|
||||
* as Raw Sector Start Address.
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_END_ADDRESS[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_SECTOR_SIZE
|
||||
* Description: external symbol from linker command file, it represents the size
|
||||
* of a FLASH sector
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_SECTOR_SIZE[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_MAX_SECTORS
|
||||
* Description: external symbol from linker command file, it represents the sectors
|
||||
* count used by the ENVM storage system; it has to be a multiple of 2
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_MAX_SECTORS[];
|
||||
|
||||
/*
|
||||
* Name: NV_STORAGE_START_ADDRESS
|
||||
* Description: NV_STORAGE_START_ADDRESS from linker command file is used by this code
|
||||
* as Raw Sector End Address. Start is End address
|
||||
*/
|
||||
extern uint32_t NV_STORAGE_START_ADDRESS[];
|
||||
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/* Flash address of the Product Data sector */
|
||||
#if defined(__CC_ARM)
|
||||
extern uint32_t Load$$LR$$LR_Prod_Data$$Base[];
|
||||
#define FREESCALE_PROD_DATA_BASE_ADDR Load$$LR$$LR_Prod_Data$$Base
|
||||
#else
|
||||
extern uint32_t FREESCALE_PROD_DATA_BASE_ADDR[];
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! GCC would warn about packing, so add pragma to repress warning */
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
typedef PACKED_STRUCT hardwareParameters_tag
|
||||
{
|
||||
uint8_t identificationWord[10]; /* valid data present */
|
||||
#ifdef CPU_JN518X
|
||||
uint8_t flash_audit_done;
|
||||
uint8_t reserved[3];
|
||||
#else
|
||||
uint8_t reserved[32]; /* for backward compatibillity */
|
||||
uint8_t ieee_802_15_4_address[8]; /* IEEE 802.15.4 MAC address */
|
||||
uint8_t bluetooth_address[6]; /* Bluetooth address */
|
||||
uint32_t xtalTrim; /* KW4x only */
|
||||
uint32_t edCalibrationOffset; /* KW01 ED offset */
|
||||
uint32_t pllFStepOffset; /* KW01 fine tune pll */
|
||||
#endif
|
||||
uint32_t gInternalStorageAddr; /* The start address of the internal storage used for OTA update.
|
||||
A value of 0xFFFFFFFF means that the External storage is used.
|
||||
Warning: The offset to this field in respect to the start address of the structure
|
||||
must not be changed.*/
|
||||
/* For forward compatibility additional fields may be added here
|
||||
Existing data in flash will not be compatible after modifying the hardwareParameters_t typedef*/
|
||||
uint16_t hardwareParamsCrc; /* crc for data between start of reserved area and start of hardwareParamsCrc field (not included). */
|
||||
}hardwareParameters_t;
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
extern flash_config_t gFlashConfig;
|
||||
|
||||
extern hardwareParameters_t gHardwareParameters;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void NV_Init(void);
|
||||
|
||||
uint32_t NV_FlashProgram( uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData);
|
||||
|
||||
uint32_t NV_FlashProgramUnaligned(uint32_t dest,
|
||||
uint32_t size,
|
||||
uint8_t* pData);
|
||||
|
||||
uint32_t NV_FlashEraseSector(uint32_t dest,
|
||||
uint32_t size);
|
||||
|
||||
#if defined(CPU_JN518X)
|
||||
#define FLASH_ERASE_AREA(ADDR, SZ) FLASH_Erase(FLASH, (uint8_t *)(ADDR), (uint8_t *)((ADDR) + (SZ) - 1))
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(FLASH, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(FLASH)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) FLASH_BlankCheck(FLASH, (uint8_t *)(ADDR), (uint8_t *)((ADDR) + (SZ) - 1))
|
||||
#elif defined(CPU_QN908X)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) SwFlashVerifyErase((ADDR), (SZ), ,kFLASH_MarginValueNormal)
|
||||
#define FLASH_ERASE_AREA(ADDR, SZ) FLASH_Erase(&gFlashConfig, (ADDR), (SZ))
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(&gFlashConfig, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(&gFlashConfig)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) SwFlashVerifyErase ((ADDR), (SZ))
|
||||
#else
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) NV_FlashVerifyErase(ADDR, SZ)
|
||||
#define FLASH_ERASE_AREA, SZ) FLASH_Erase(&gFlashConfig, (ADDR), (SZ), kFLASH_ApiEraseKey)
|
||||
#define FLASH_PROGRAM_AREA(ADDR, SRC, SZ) FLASH_Program(&gFlashConfig, (uint32_t *)(ADDR), (uint32_t*)(SRC), (SZ))
|
||||
#define FLASH_INIT() FLASH_Init(&gFlashConfig)
|
||||
#define FLASH_VERIFY_ERASE(ADDR, SZ) FLASH_VerifyErase(&gFlashConfig, (ADDR), (SZ), kFLASH_MarginValueNormal)
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t NV_ReadHWParameters(hardwareParameters_t *pHwParams);
|
||||
|
||||
uint32_t NV_WriteHWParameters(hardwareParameters_t *pHwParams);
|
||||
|
||||
void NV_Flash_SetCriticalSection(void);
|
||||
void NV_Flash_ClearCriticalSection(void);
|
||||
|
||||
#endif /* __FLASH_ADAPTER_H__ */
|
||||
Vendored
Executable
+573
@@ -0,0 +1,573 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This module contains various common functions like copy and compare routines.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#include "FunctionLib.h"
|
||||
|
||||
#if gUseToolchainMemFunc_d
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if gFLib_CheckBufferOverflow_d
|
||||
#include "MemManager.h"
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies bytes from one buffer to another.
|
||||
* The buffers should not overlap.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post The source and destination buffers must not overlap.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpy (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
|
||||
#if gUseToolchainMemFunc_d
|
||||
memcpy(pDst, pSrc, cBytes);
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = ((uint8_t*)pDst)+1;
|
||||
pSrc = ((uint8_t*)pSrc)+1;
|
||||
cBytes--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies the specified number of bytes from the
|
||||
* source address to the destination address. No attempt is made
|
||||
* to handle overlapping copies to prevent loss of data.
|
||||
* The copying is optimized to avoid alignment problems, and attempts
|
||||
* to copy 32bit numbers optimally.
|
||||
*
|
||||
* \param[in] from_ptr Pointer to the source buffer.
|
||||
*
|
||||
* \param[in, out] to_ptr Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] number_of_bytes Number of bytes to copy (32 bit value).
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyAligned32bit (void* to_ptr,
|
||||
const void* from_ptr,
|
||||
register uint32_t number_of_bytes)
|
||||
{
|
||||
uint8_t* from8_ptr = (uint8_t*)from_ptr;
|
||||
uint8_t* to8_ptr = (uint8_t*)to_ptr;
|
||||
uint16_t* from16_ptr = (uint16_t*)from_ptr;
|
||||
uint16_t* to16_ptr = (uint16_t*)to_ptr;
|
||||
register uint32_t* from32_ptr = (uint32_t*)from_ptr;
|
||||
register uint32_t* to32_ptr = (uint32_t*)to_ptr;
|
||||
|
||||
register uint32_t loops;
|
||||
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(to_ptr, number_of_bytes);
|
||||
#endif
|
||||
|
||||
if (number_of_bytes > 3)
|
||||
{
|
||||
/* Try to align source on word */
|
||||
if ((uint32_t)from_ptr & 1)
|
||||
{
|
||||
from8_ptr = (uint8_t*)from_ptr;
|
||||
to8_ptr = (uint8_t*)to_ptr;
|
||||
|
||||
*to8_ptr++ = *from8_ptr++;
|
||||
|
||||
from_ptr = from8_ptr;
|
||||
to_ptr = to8_ptr;
|
||||
--number_of_bytes;
|
||||
}
|
||||
|
||||
/* Try to align source on longword */
|
||||
if ((uint32_t)from_ptr & 2)
|
||||
{
|
||||
from16_ptr = (uint16_t*)from_ptr;
|
||||
to16_ptr = (uint16_t*)to_ptr;
|
||||
|
||||
*to16_ptr++ = *from16_ptr++;
|
||||
|
||||
from_ptr = from16_ptr;
|
||||
to_ptr = to16_ptr;
|
||||
number_of_bytes -= 2;
|
||||
}
|
||||
|
||||
from32_ptr = (uint32_t*)from_ptr;
|
||||
to32_ptr = (uint32_t*)to_ptr;
|
||||
|
||||
for (loops = number_of_bytes >> 2; loops != 0; loops--)
|
||||
{
|
||||
*to32_ptr++ = *from32_ptr++;
|
||||
}
|
||||
|
||||
from_ptr = from32_ptr;
|
||||
to_ptr = to32_ptr;
|
||||
}
|
||||
|
||||
/* Copy all remaining bytes */
|
||||
if (number_of_bytes & 2)
|
||||
{
|
||||
from16_ptr = (uint16_t*)from_ptr;
|
||||
to16_ptr = (uint16_t*)to_ptr;
|
||||
|
||||
*to16_ptr++ = *from16_ptr++;
|
||||
|
||||
from_ptr = from16_ptr;
|
||||
to_ptr = to16_ptr;
|
||||
}
|
||||
|
||||
if (number_of_bytes & 1)
|
||||
{
|
||||
*(uint8_t*)to_ptr = *(uint8_t*)from_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes from one buffer to another. The buffers should not overlap.
|
||||
* The function can copy in either direction. If 'dir' is TRUE, then the function
|
||||
* works like FLib_MemCpy(). If FALSE, the function swaps the buffer pointers
|
||||
* before copying.
|
||||
*
|
||||
* \param[in, out] pBuf1 Pointer to the destination/source buffer.
|
||||
*
|
||||
* \param[in, out] pBuf2 Pointer to the source/destination buffer.
|
||||
*
|
||||
* \param[in] dir Direction to copy: pBuf2->pBuf1 if TRUE, pBuf1->pBuf2 if FALSE
|
||||
*
|
||||
* \param[in] n Number of bytes to copy.
|
||||
*
|
||||
* \post The source and destination buffers must not overlap.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyDir (void* pBuf1,
|
||||
void* pBuf2,
|
||||
bool_t dir,
|
||||
uint32_t n)
|
||||
{
|
||||
if (dir)
|
||||
{
|
||||
FLib_MemCpy (pBuf1, pBuf2, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLib_MemCpy (pBuf2, pBuf1, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief The byte at index i from the source buffer is copied to index ((n-1) - i)
|
||||
* in the destination buffer (and vice versa).
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyReverseOrder (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
if(cBytes)
|
||||
{
|
||||
pDst = (uint8_t*)pDst + (uint32_t)(cBytes-1);
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = (uint8_t*)pDst-1;
|
||||
pSrc = (uint8_t*)pSrc+1;
|
||||
cBytes--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function compares two buffers.
|
||||
*
|
||||
* \param[in] pData1 First buffer to compare.
|
||||
*
|
||||
* \param[in] pData2 Second buffer to compare.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to compare.
|
||||
*
|
||||
* \return This function return TRUE if the buffers are equal and FALSE otherwise.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmp (const void* pData1, /* IN: First memory block to compare */
|
||||
const void* pData2, /* IN: Second memory block to compare */
|
||||
uint32_t cBytes /* IN: Number of bytes to compare. */
|
||||
)
|
||||
{
|
||||
bool_t status = TRUE;
|
||||
#if gUseToolchainMemFunc_d
|
||||
if( memcmp(pData1, pData2, cBytes) )
|
||||
{
|
||||
status = FALSE;
|
||||
}
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
if ( *((uint8_t *)pData1) != *((uint8_t *)pData2))
|
||||
{
|
||||
status = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
pData2 = (uint8_t* )pData2+1;
|
||||
pData1 = (uint8_t* )pData1+1;
|
||||
cBytes--;
|
||||
}
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function compares each octet of a given location to a value.
|
||||
*
|
||||
* \param [in] pAddr location to be compared
|
||||
*
|
||||
* \param [in] val reference value
|
||||
*
|
||||
* \param [in] len length of location to be compared
|
||||
*
|
||||
* \return This function return TRUE if all octests match and FALSE otherwise.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmpToVal
|
||||
(
|
||||
const void* pAddr,
|
||||
uint8_t val,
|
||||
uint32_t len
|
||||
)
|
||||
{
|
||||
while(len)
|
||||
{
|
||||
len--;
|
||||
|
||||
if(((uint8_t *)pAddr)[len] != val)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function resets all bytes in a specified buffer to a set value.
|
||||
*
|
||||
* \param[in,out] pDst Address of the buffer to set.
|
||||
*
|
||||
* \param[in] value Set value.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to set in the buffer (maximum 255 bytes).
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemSet (void* pData,
|
||||
uint8_t value,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pData, cBytes);
|
||||
#endif
|
||||
#if gUseToolchainMemFunc_d
|
||||
memset(pData, value, cBytes);
|
||||
#else
|
||||
while (cBytes)
|
||||
{
|
||||
((uint8_t* )pData)[--cBytes] = value;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a buffer,
|
||||
* possibly into the same overlapping memory as it is taken from
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemInPlaceCpy (void* pDst,
|
||||
void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
#if gFLib_CheckBufferOverflow_d && defined(MEM_TRACKING)
|
||||
(void)MEM_BufferCheck(pDst, cBytes);
|
||||
#endif
|
||||
if (pDst != pSrc)
|
||||
{
|
||||
/* Do nothing if copying to same position */
|
||||
if (pDst < pSrc)
|
||||
{
|
||||
/* If dst is before src in memory copy forward */
|
||||
while (cBytes)
|
||||
{
|
||||
*((uint8_t*)pDst) = *((uint8_t*)pSrc);
|
||||
pDst = ((uint8_t*)pDst)+1;
|
||||
pSrc = ((uint8_t*)pSrc)+1;
|
||||
cBytes--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If dst is after src in memory copy backward */
|
||||
while(cBytes)
|
||||
{
|
||||
cBytes--;
|
||||
((uint8_t* )pDst)[cBytes] = ((uint8_t* )pSrc)[cBytes];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 16bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val16 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy16Unaligned (void* pDst,
|
||||
uint16_t val16)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val16);
|
||||
*pData = (uint8_t)(val16 >> 8);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 32bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val32 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy32Unaligned (void* pDst,
|
||||
uint32_t val32)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val32);
|
||||
*pData++ = (uint8_t)(val32 >> 8);
|
||||
*pData++ = (uint8_t)(val32 >> 16);
|
||||
*pData++ = (uint8_t)(val32 >> 24);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies a 64bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination memory block.
|
||||
*
|
||||
* \param[in] val64 The value to be copied.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy64Unaligned (void* pDst,
|
||||
uint64_t val64)
|
||||
{
|
||||
uint8_t* pData = (uint8_t*)pDst;
|
||||
|
||||
*pData++ = (uint8_t)(val64);
|
||||
*pData++ = (uint8_t)(val64 >> 8);
|
||||
*pData++ = (uint8_t)(val64 >> 16);
|
||||
*pData++ = (uint8_t)(val64 >> 24);
|
||||
*pData++ = (uint8_t)(val64 >> 32);
|
||||
*pData++ = (uint8_t)(val64 >> 40);
|
||||
*pData++ = (uint8_t)(val64 >> 48);
|
||||
*pData = (uint8_t)(val64 >> 56);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function adds an offset to a pointer.
|
||||
*
|
||||
* \param[in,out] pPtr Pointer to the pointer to add the offset to
|
||||
*
|
||||
* \param[in] offset Offset to add to the specified pointer.
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_AddOffsetToPointer (void** pPtr,
|
||||
uint32_t offset)
|
||||
{
|
||||
(*pPtr) = ((uint8_t* )*pPtr) + offset;
|
||||
}
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the length of a NULL terminated string.
|
||||
*
|
||||
* \param[in] str A NULL terminated string
|
||||
*
|
||||
* \return the size of string in bytes
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t FLib_StrLen(const char *str)
|
||||
{
|
||||
#if gUseToolchainMemFunc_d
|
||||
return strlen(str);
|
||||
#else
|
||||
register uint32_t len=0;
|
||||
|
||||
while(*str != '\0')
|
||||
{
|
||||
str++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
/*! *********************************************************************************
|
||||
* \brief This function copies bytes from FLASH to ram.
|
||||
*
|
||||
* \param[in, out] pDst Pointer to the destination buffer.
|
||||
*
|
||||
* \param[in] pSrc Pointer to the source buffer.
|
||||
*
|
||||
* \param[in] cBytes Number of bytes to copy.
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
bool_t raise_error = FALSE;
|
||||
|
||||
TRY
|
||||
{
|
||||
FLib_MemCpy(pDst, pSrc, cBytes);
|
||||
}
|
||||
CATCH (BUS_EXCEPTION)
|
||||
{
|
||||
raise_error = TRUE;
|
||||
}
|
||||
YRT;
|
||||
|
||||
return raise_error;
|
||||
}
|
||||
#else
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes)
|
||||
{
|
||||
FLib_MemCpy(pDst, pSrc, cBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
Executable
+320
@@ -0,0 +1,320 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the Function Lib module header file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _FUNCTION_LIB_H_
|
||||
#define _FUNCTION_LIB_H_
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef gUseToolchainMemFunc_d
|
||||
#define gUseToolchainMemFunc_d 0
|
||||
#endif
|
||||
|
||||
#ifndef gFLib_CheckBufferOverflow_d
|
||||
#define gFLib_CheckBufferOverflow_d 0
|
||||
#endif
|
||||
|
||||
#define FLib_MemSet16 FLib_MemSet
|
||||
|
||||
|
||||
extern jmp_buf *exception_buf;
|
||||
#define TRY do {jmp_buf exc_buf; \
|
||||
jmp_buf *old_buf = exception_buf; \
|
||||
exception_buf = &exc_buf; \
|
||||
switch (setjmp(exc_buf)) { case 0:
|
||||
|
||||
#define CATCH(x) break; case x:
|
||||
#define YRT } exception_buf = old_buf; } while(0)
|
||||
|
||||
typedef enum {
|
||||
BUS_EXCEPTION = 1,
|
||||
} EXCEPTION_ERROR_T;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy the content of one memory block to another. The amount of data to copy
|
||||
* must be specified in number of bytes.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpy (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
void FLib_MemCpyAligned32bit (void* to_ptr,
|
||||
const void* from_ptr,
|
||||
register uint32_t number_of_bytes);
|
||||
|
||||
void FLib_MemCpyDir (void* pBuf1,
|
||||
void* pBuf2,
|
||||
bool_t dir,
|
||||
uint32_t n);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes. The byte at index i from the source buffer is copied to index
|
||||
* ((n-1) - i) in the destination buffer (and vice versa).
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCpyReverseOrder (void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare two memory blocks. The number of bytes to compare must be specified.
|
||||
* If the blocks are equal byte by byte, the function returns TRUE,
|
||||
* and FALSE otherwise.
|
||||
*
|
||||
* \param[in] pData1 First memory block to compare
|
||||
* \param[in] pData2 Second memory block to compare
|
||||
* \param[in] cBytes Number of bytes to compare
|
||||
*
|
||||
* \return TRUE if memory areas are equal. FALSE othwerwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmp (const void* pData1,
|
||||
const void* pData2,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare each byte of a memory block to a given value. The number of bytes to compare
|
||||
must be specified.
|
||||
* If all the bytes are equal to the given value, the function returns TRUE,
|
||||
* and FALSE otherwise.
|
||||
*
|
||||
* \param[in] pAddr Location to be compared
|
||||
* \param[in] val Reference value
|
||||
* \param[in] length Number of bytes to compare
|
||||
*
|
||||
* \return TRUE if all bytes match and FALSE otherwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
bool_t FLib_MemCmpToVal(const void* pAddr,
|
||||
uint8_t val,
|
||||
uint32_t len
|
||||
);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Reset bytes in a memory block to a certain value. The value, and the number
|
||||
* of bytes to be set, are supplied as arguments.
|
||||
*
|
||||
* \param[in] pData Pointer to memory block to reset
|
||||
* \param[in] value Value that memory block will be set to
|
||||
* \param[in] cBytes Number of bytes to set
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemSet (void* pData,
|
||||
uint8_t value,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copy bytes, possibly into the same overlapping memory as it is taken from
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] pSrc Pointer to source memory block
|
||||
* \param[in] cBytes Number of bytes to copy
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemInPlaceCpy (void* pDst,
|
||||
void* pSrc,
|
||||
uint32_t cBytes
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 16bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val16 The 16-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy16Unaligned (void* pDst,
|
||||
uint16_t val16
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 32bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val32 The 32-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy32Unaligned (void* pDst,
|
||||
uint32_t val32
|
||||
);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Copies a 64bit value to an unaligned a memory block.
|
||||
*
|
||||
* \param[out] pDst Pointer to destination memory block
|
||||
* \param[in] val64 The 64-bit value to be copied
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_MemCopy64Unaligned (void* pDst,
|
||||
uint64_t val64
|
||||
);
|
||||
|
||||
|
||||
bool_t FLib_CopyFromFlash(void* pDst,
|
||||
const void* pSrc,
|
||||
uint32_t cBytes);
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Add an offset to a pointer.
|
||||
*
|
||||
* \param[out] pPtr Pointer to the pointer to be updated
|
||||
* \param[in] offset The offset(in bytes) to be added
|
||||
*
|
||||
********************************************************************************** */
|
||||
void FLib_AddOffsetToPointer (void** pPtr,
|
||||
uint32_t offset);
|
||||
|
||||
#define FLib_AddOffsetToPtr(pPtr,offset) FLib_AddOffsetToPointer((void**)(pPtr),(offset))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the length of a NULL terminated string.
|
||||
*
|
||||
* \param[in] str A NULL terminated string
|
||||
*
|
||||
* \return the size of string in bytes
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t FLib_StrLen(const char *str);
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Compare two bytes.
|
||||
*
|
||||
* \param[in] pCmp1 pointer to the first 2-byte compare value
|
||||
* \param[in] pCmp2 pointer to the second 2-byte compare value
|
||||
*
|
||||
* \return TRUE if the two bytes are equal, and FALSE otherwise.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_Cmp2Bytes(pCmp1, pCmp2) ((((uint8_t *)(pCmp1))[0] == ((uint8_t *)(pCmp2))[0]) && \
|
||||
(((uint8_t *)(pCmp1))[1] == ((uint8_t *)(pCmp2))[1]))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Returns the maximum value of arguments a and b.
|
||||
*
|
||||
* \return The maximum value of arguments a and b
|
||||
*
|
||||
* \remarks
|
||||
* The primitive should must be implemented as a macro, as it should be possible to
|
||||
* evaluate the result on compile time if the arguments are constants.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_GetMax(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Returns the minimum value of arguments a and b.
|
||||
*
|
||||
* \return The minimum value of arguments a and b
|
||||
*
|
||||
* \remarks
|
||||
* The primitive should must be implemented as a macro, as it should be possible to
|
||||
* evaluate the result on compile time if the arguments are constants.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#define FLib_GetMin(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _CLZ(x) __builtin_clz(x)
|
||||
#endif
|
||||
#if defined (__IAR_SYSTEMS_ICC__)
|
||||
#define _CLZ(x) __CLZ(x)
|
||||
#endif
|
||||
#define _BSR(x) (31 - _CLZ(x))
|
||||
|
||||
static inline uint32_t Flib_Log2(uint32_t x)
|
||||
{
|
||||
uint32_t msb = _BSR(x);
|
||||
/* if not a power of 2, round to next so that x remains <= (1<<msb) */
|
||||
if (x > (1<< msb)) msb++;
|
||||
return msb;
|
||||
}
|
||||
|
||||
|
||||
#define LOG_1(n) (((n) >= 2) ? 1 : 0)
|
||||
#define LOG_2(n) (((n) >= 1<<2) ? (2 + LOG_1((n)>>2)) : LOG_1(n))
|
||||
#define LOG_4(n) (((n) >= 1<<4) ? (4 + LOG_2((n)>>4)) : LOG_2(n))
|
||||
#define LOG_8(n) (((n) >= 1<<8) ? (8 + LOG_4((n)>>8)) : LOG_4(n))
|
||||
#define LOG(n) (((n) >= 1<<16) ? (16 + LOG_8((n)>>16)) : LOG_8(n))
|
||||
|
||||
|
||||
|
||||
|
||||
#define MASK_LOG(log) ((1<<(log))-1)
|
||||
#define ROUND_FLOOR(x, log) (((x) >> (log)) << (log))
|
||||
#define ROUND_CEIL(x, log) ((((x) + MASK_LOG(log) ) >> (log)) << (log))
|
||||
#define IS_POW_OF_TWO(x) (((x) & ((x)-1)) == 0)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FUNCTION_LIB_H_ */
|
||||
+561
@@ -0,0 +1,561 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the linked lists part of the Utils package.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "GenericList.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! *********************************************************************************
|
||||
* \brief Initialises the list descriptor.
|
||||
*
|
||||
* \param[in] list - List handle to init.
|
||||
* max - Maximum number of elements in list. 0 for unlimited.
|
||||
*
|
||||
* \return void.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
void ListInit(listHandle_t list, uint32_t max)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->max = max;
|
||||
list->size = 0;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the list that contains the given element.
|
||||
*
|
||||
* \param[in] element - Handle of the element.
|
||||
*
|
||||
* \return NULL if element is orphan.
|
||||
* Handle of the list the element is inserted into.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listHandle_t ListGetList(listElementHandle_t element)
|
||||
{
|
||||
return element->list;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links element to the tail of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to insert into.
|
||||
* element - element to add
|
||||
*
|
||||
* \return gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddTail(listHandle_t list, listElementHandle_t element)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (list->max != 0) && (list->max == list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->head = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail->next = element;
|
||||
}
|
||||
element->prev = list->tail;
|
||||
element->next = NULL;
|
||||
element->list = list;
|
||||
list->tail = element;
|
||||
list->size++;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links element to the head of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to insert into.
|
||||
* element - element to add
|
||||
*
|
||||
* \return gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddHead(listHandle_t list, listElementHandle_t element)
|
||||
{
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (list->max != 0) && (list->max == list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->tail = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head->prev = element;
|
||||
}
|
||||
element->next = list->head;
|
||||
element->prev = NULL;
|
||||
element->list = list;
|
||||
list->head = element;
|
||||
list->size++;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Unlinks element from the head of the list.
|
||||
*
|
||||
* \param[in] list - ID of list to remove from.
|
||||
*
|
||||
* \return NULL if list is empty.
|
||||
* ID of removed element(pointer) if removal was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListRemoveHead(listHandle_t list)
|
||||
{
|
||||
listElementHandle_t element;
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if((NULL == list) || (list->size == 0))
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return NULL; /*List is empty*/
|
||||
}
|
||||
|
||||
element = list->head;
|
||||
list->size--;
|
||||
if(list->size == 0)
|
||||
{
|
||||
list->tail = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
element->next->prev = NULL;
|
||||
}
|
||||
list->head = element->next; /*Is NULL if element is head*/
|
||||
element->list = NULL;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return element;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets head element ID.
|
||||
*
|
||||
* \param[in] list - ID of list.
|
||||
*
|
||||
* \return NULL if list is empty.
|
||||
* ID of head element if list is not empty.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetHead(listHandle_t list)
|
||||
{
|
||||
return list->head;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets next element ID.
|
||||
*
|
||||
* \param[in] element - ID of the element.
|
||||
*
|
||||
* \return NULL if element is tail.
|
||||
* ID of next element if exists.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetNext(listElementHandle_t element)
|
||||
{
|
||||
return element->next;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets previous element ID.
|
||||
*
|
||||
* \param[in] element - ID of the element.
|
||||
*
|
||||
* \return NULL if element is head.
|
||||
* ID of previous element if exists.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listElementHandle_t ListGetPrev(listElementHandle_t element)
|
||||
{
|
||||
return element->prev;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Unlinks an element from its list.
|
||||
*
|
||||
* \param[in] element - ID of the element to remove.
|
||||
*
|
||||
* \return gOrphanElement_c if element is not part of any list.
|
||||
* gListOk_c if removal was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListRemoveElement(listElementHandle_t element)
|
||||
{
|
||||
if(element->list == NULL)
|
||||
{
|
||||
return gOrphanElement_c; /*Element was previusly removed or never added*/
|
||||
}
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if(element->prev == NULL) /*Element is head or solo*/
|
||||
{
|
||||
element->list->head = element->next; /*is null if solo*/
|
||||
}
|
||||
if(element->next == NULL) /*Element is tail or solo*/
|
||||
{
|
||||
element->list->tail = element->prev; /*is null if solo*/
|
||||
}
|
||||
if(element->prev != NULL) /*Element is not head*/
|
||||
{
|
||||
element->prev->next = element->next;
|
||||
}
|
||||
if(element->next != NULL) /*Element is not tail*/
|
||||
{
|
||||
element->next->prev = element->prev;
|
||||
}
|
||||
element->list->size--;
|
||||
element->list = NULL;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Links an element in the previous position relative to a given member
|
||||
* of a list.
|
||||
*
|
||||
* \param[in] element - ID of a member of a list.
|
||||
* newElement - new element to insert before the given member.
|
||||
*
|
||||
* \return gOrphanElement_c if element is not part of any list.
|
||||
* gListFull_c if list is full.
|
||||
* gListOk_c if insertion was successful.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
listStatus_t ListAddPrevElement(listElementHandle_t element, listElementHandle_t newElement)
|
||||
{
|
||||
if(element->list == NULL)
|
||||
{
|
||||
return gOrphanElement_c; /*Element was previusly removed or never added*/
|
||||
}
|
||||
OSA_InterruptDisable();
|
||||
|
||||
if( (element->list->max != 0) && (element->list->max == element->list->size) )
|
||||
{
|
||||
OSA_InterruptEnable();
|
||||
return gListFull_c;
|
||||
}
|
||||
|
||||
if(element->prev == NULL) /*Element is list head*/
|
||||
{
|
||||
element->list->head = newElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
element->prev->next = newElement;
|
||||
}
|
||||
newElement->list = element->list;
|
||||
element->list->size++;
|
||||
newElement->next = element;
|
||||
newElement->prev = element->prev;
|
||||
element->prev = newElement;
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return gListOk_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the current size of a list.
|
||||
*
|
||||
* \param[in] list - ID of the list.
|
||||
*
|
||||
* \return Current size of the list.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t ListGetSize(listHandle_t list)
|
||||
{
|
||||
return list->size;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Gets the number of free places in the list.
|
||||
*
|
||||
* \param[in] list - ID of the list.
|
||||
*
|
||||
* \return Available size of the list.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t ListGetAvailable(listHandle_t list)
|
||||
{
|
||||
return (list->max - list->size);
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Creates, tests and deletes a list. Any error that occurs will trap the
|
||||
* CPU in a while(1) loop.
|
||||
*
|
||||
* \param[in] void.
|
||||
*
|
||||
* \return gListOk_c.
|
||||
*
|
||||
* \pre
|
||||
*
|
||||
* \post
|
||||
*
|
||||
* \remarks
|
||||
*
|
||||
********************************************************************************** */
|
||||
/* To be removed or rewritten to remove MemManager dependency. */
|
||||
#if 0
|
||||
listStatus_t ListTest()
|
||||
{
|
||||
listHandle_t list;
|
||||
listElementHandle_t element, newElement;
|
||||
uint32_t i,freeBlocks;
|
||||
const uint32_t max = 10;
|
||||
|
||||
freeBlocks = MEM_GetAvailableFwkBlocks(0);
|
||||
/*create list*/
|
||||
list = ListCreate(max);
|
||||
LIST_ASSERT(list != NULL);
|
||||
|
||||
/*add elements*/
|
||||
for(i=0; i<max; i++)
|
||||
{
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListAddHead(list, element) == gListOk_c);
|
||||
LIST_ASSERT(list->head == element)
|
||||
ListRemoveHead(list);
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListOk_c);
|
||||
LIST_ASSERT(list->tail == element);
|
||||
if(ListGetSize(list) == 1)
|
||||
{
|
||||
LIST_ASSERT(list->head == element);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_ASSERT(list->head != element);
|
||||
}
|
||||
}
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
|
||||
/*add one more element*/
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListFull_c);
|
||||
list->max = 0;
|
||||
LIST_ASSERT(ListAddTail(list, element) == gListOk_c);
|
||||
LIST_ASSERT(ListGetSize(list) == max+1);
|
||||
/*remove the extra element*/
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
LIST_ASSERT(MEM_BufferFree(element) == MEM_SUCCESS_c);
|
||||
list->max = max;
|
||||
|
||||
/*parse elements*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListGetNext(element);
|
||||
LIST_ASSERT(element != NULL);
|
||||
}
|
||||
LIST_ASSERT(element == list->tail);
|
||||
LIST_ASSERT(ListGetNext(element) == NULL);
|
||||
|
||||
/*Reverse parse elements*/
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListGetPrev(element);
|
||||
LIST_ASSERT(element != NULL);
|
||||
}
|
||||
LIST_ASSERT(element == list->head);
|
||||
LIST_ASSERT(ListGetPrev(element) == NULL);
|
||||
|
||||
/*Add prev*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListFull_c);
|
||||
LIST_ASSERT(ListGetHead(list) == element);
|
||||
list->max = 0;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(ListGetHead(list) == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = list->head->next->next;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(list->head->next->next == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = list->tail;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gListOk_c);
|
||||
LIST_ASSERT(list->tail->prev == newElement);
|
||||
newElement = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(newElement != NULL);
|
||||
element = (listElementHandle_t)MEM_BufferFwkAlloc(sizeof(listElement_t));
|
||||
LIST_ASSERT(element != NULL);
|
||||
element->list = NULL;
|
||||
LIST_ASSERT(ListAddPrevElement(element, newElement) == gOrphanElement_c);
|
||||
MEM_BufferFree(newElement);
|
||||
MEM_BufferFree(element);
|
||||
LIST_ASSERT(ListGetSize(list) == max+3);
|
||||
|
||||
/*Remove element*/
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element == list->head);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->head != element);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gOrphanElement_c);
|
||||
MEM_BufferFree(element);
|
||||
element = ListGetHead(list)->next->next;
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
MEM_BufferFree(element);
|
||||
element = list->tail;
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->tail != element);
|
||||
MEM_BufferFree(element);
|
||||
LIST_ASSERT(ListGetSize(list) == max);
|
||||
list->max = max;
|
||||
|
||||
for(i=0; i<(max-1); i++)
|
||||
{
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
MEM_BufferFree(element);
|
||||
}
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element != NULL);
|
||||
LIST_ASSERT(ListRemoveElement(element) == gListOk_c);
|
||||
LIST_ASSERT(list->head == NULL);
|
||||
LIST_ASSERT(list->tail == NULL);
|
||||
LIST_ASSERT(element->list == NULL);
|
||||
MEM_BufferFree(element);
|
||||
|
||||
/*List is empty here.*/
|
||||
LIST_ASSERT(ListGetSize(list) == 0);
|
||||
element = ListRemoveHead(list);
|
||||
LIST_ASSERT(element == NULL);
|
||||
element = ListGetHead(list);
|
||||
LIST_ASSERT(element == NULL);
|
||||
|
||||
MEM_BufferFree(list);
|
||||
/*Did we produce a memory leak?*/
|
||||
LIST_ASSERT(freeBlocks == MEM_GetAvailableFwkBlocks(0));
|
||||
|
||||
return gListOk_c;
|
||||
}
|
||||
#else
|
||||
listStatus_t ListTest(void)
|
||||
{
|
||||
return gListOk_c;
|
||||
}
|
||||
#endif
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the linked lists part of the Utils package.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _GENERIC_LIST_H_
|
||||
#define _GENERIC_LIST_H_
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macro definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
typedef enum
|
||||
{
|
||||
gListOk_c = 0,
|
||||
gListFull_c,
|
||||
gListEmpty_c,
|
||||
gOrphanElement_c
|
||||
}listStatus_t;
|
||||
|
||||
typedef struct list_tag
|
||||
{
|
||||
struct listElement_tag *head;
|
||||
struct listElement_tag *tail;
|
||||
uint16_t size;
|
||||
uint16_t max;
|
||||
}list_t, *listHandle_t;
|
||||
|
||||
typedef struct listElement_tag
|
||||
{
|
||||
struct listElement_tag *next;
|
||||
struct listElement_tag *prev;
|
||||
struct list_tag *list;
|
||||
}listElement_t, *listElementHandle_t;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void ListInit(listHandle_t list, uint32_t max);
|
||||
listHandle_t ListGetList(listElementHandle_t element);
|
||||
listStatus_t ListAddHead(listHandle_t list, listElementHandle_t element);
|
||||
listStatus_t ListAddTail(listHandle_t list, listElementHandle_t element);
|
||||
listElementHandle_t ListRemoveHead(listHandle_t list);
|
||||
listElementHandle_t ListGetHead(listHandle_t list);
|
||||
listElementHandle_t ListGetNext(listElementHandle_t element);
|
||||
listElementHandle_t ListGetPrev(listElementHandle_t element);
|
||||
listStatus_t ListRemoveElement(listElementHandle_t element);
|
||||
listStatus_t ListAddPrevElement(listElementHandle_t element, listElementHandle_t newElement);
|
||||
uint32_t ListGetSize(listHandle_t list);
|
||||
uint32_t ListGetAvailable(listHandle_t list);
|
||||
listStatus_t ListTest(void);
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifdef DEBUG_ASSERT
|
||||
#define LIST_ASSERT(condition) if(!(condition))while(1);
|
||||
#else
|
||||
#define LIST_ASSERT(condition) (void)(condition);
|
||||
#endif
|
||||
|
||||
#endif /*_GENERIC_LIST_H_*/
|
||||
Vendored
Executable
+223
@@ -0,0 +1,223 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the Memory Manager interface.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef _MEM_MANAGER_H_
|
||||
#define _MEM_MANAGER_H_
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include <stddef.h>
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "GenericList.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Defines pools by block size and number of blocks. Must be alligned to 4 bytes.*/
|
||||
#ifndef PoolsDetails_c
|
||||
#define PoolsDetails_c \
|
||||
_block_size_ 64 _number_of_blocks_ 8 _pool_id_(0) _eol_ \
|
||||
_block_size_ 128 _number_of_blocks_ 2 _pool_id_(0) _eol_ \
|
||||
_block_size_ 256 _number_of_blocks_ 6 _pool_id_(0) _eol_
|
||||
#endif
|
||||
|
||||
#if defined (__IAR_SYSTEMS_ICC__)
|
||||
/* __get_LR() declaration not included to avoid issues with different versions of IAR compiler */
|
||||
#elif defined(__GNUC__)
|
||||
#define __get_LR() __builtin_return_address(0)
|
||||
#elif defined(__CC_ARM)
|
||||
#define __get_LR() __return_address()
|
||||
#endif
|
||||
|
||||
/* If a buffer (that is not allocated forever using MEM_BufferAllocForever()) is not freed
|
||||
in MEM_CheckMemBufferThreshold_c ms, the device will enter into panic */
|
||||
#ifndef MEM_CheckMemBufferThreshold_c
|
||||
#define MEM_CheckMemBufferThreshold_c 120000 /* ms */
|
||||
#endif
|
||||
|
||||
/* How often the device should check if the above threshold expired */
|
||||
#ifndef MEM_CheckMemBufferInterval_c
|
||||
#define MEM_CheckMemBufferInterval_c 15000 /* ms */
|
||||
#endif
|
||||
|
||||
/* Default memory allocator */
|
||||
#ifndef MEM_BufferAlloc
|
||||
#define MEM_BufferAlloc(numBytes) MEM_BufferAllocWithId(numBytes, 0, (void*)__get_LR())
|
||||
#endif
|
||||
|
||||
/* Allocate a block from the memory pools forever.*/
|
||||
#define MEM_BufferAllocForever(numBytes,poolId) MEM_BufferAllocWithId(numBytes, poolId, (void*)((uintptr_t)__get_LR() | 0x80000000 ))
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Defines statuses used in MEM_BufferAlloc and MEM_BufferFree*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_SUCCESS_c = 0, /* No error occurred */
|
||||
MEM_INIT_ERROR_c, /* Memory initialization error */
|
||||
MEM_ALLOC_ERROR_c, /* Memory allocation error */
|
||||
MEM_FREE_ERROR_c, /* Memory free error */
|
||||
MEM_UNKNOWN_ERROR_c /* something bad has happened... */
|
||||
}memStatus_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*Initialises the Memory Manager.*/
|
||||
memStatus_t MEM_Init(void);
|
||||
/*Returns the number of available blocks that fit the given size.*/
|
||||
uint32_t MEM_GetAvailableBlocks(uint32_t size);
|
||||
/*Frees the givem buffer.*/
|
||||
memStatus_t MEM_BufferFree(void* buffer);
|
||||
/*Returns the allocated buffer of the given size.*/
|
||||
void* MEM_BufferAllocWithId(uint32_t numBytes , uint8_t poolId, void *pCaller);
|
||||
/*Returns the size of a given buffer*/
|
||||
uint16_t MEM_BufferGetSize(void* buffer);
|
||||
/*Performs a write-read-verify test accross all pools*/
|
||||
uint32_t MEM_WriteReadTest(void);
|
||||
#if (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX))
|
||||
/*Free a buffer on the Master core*/
|
||||
memStatus_t MEM_BufferFreeOnMaster(uint8_t * pBuff);
|
||||
/*Free a buffer on the Slave core*/
|
||||
memStatus_t MEM_BufferFreeOnSlave(uint8_t * pBuff);
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if defined(MEM_TRACKING) && defined(DEBUG_ASSERT)
|
||||
#define MEM_ASSERT(condition) if(!(condition))while(1);
|
||||
#else
|
||||
#define MEM_ASSERT(condition) (void)(condition);
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
/*Statistics structure definition. Used by pools.*/
|
||||
typedef struct poolStat_tag
|
||||
{
|
||||
uint16_t numBlocks;
|
||||
uint16_t allocatedBlocks;
|
||||
uint16_t allocatedBlocksPeak;
|
||||
uint16_t allocationFailures;
|
||||
uint16_t freeFailures;
|
||||
#ifdef MEM_TRACKING
|
||||
uint16_t poolFragmentWaste;
|
||||
uint16_t poolFragmentWastePeak;
|
||||
uint16_t poolFragmentMinWaste;
|
||||
uint16_t poolFragmentMaxWaste;
|
||||
#endif /*MEM_TRACKING*/
|
||||
} poolStat_t;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
/*Definition for alloc indicators. Used in buffer tracking.*/
|
||||
typedef enum
|
||||
{
|
||||
MEM_TRACKING_FREE_c = 0,
|
||||
MEM_TRACKING_ALLOC_c,
|
||||
}memTrackingStatus_t;
|
||||
|
||||
/*Tracking structure definition.*/
|
||||
typedef PACKED_STRUCT BlockTracking_tag
|
||||
{
|
||||
void *blockAddr; /*Addr of Msg, not that this pointer is
|
||||
4 byte bigger than the addr in the pool
|
||||
has the header of the msg is 4 bytes */
|
||||
uint16_t blockSize; /*Size of block in bytes.*/
|
||||
uint16_t fragmentWaste; /*Size requested by allocator.*/
|
||||
void *allocAddr; /*Return address of last Alloc made */
|
||||
void *freeAddr; /*Return address of last Free made */
|
||||
uint16_t allocCounter; /*No of time this msg has been allocated */
|
||||
uint16_t freeCounter; /*No of time this msg has been freed */
|
||||
memTrackingStatus_t allocStatus; /*1 if currently allocated, 0 if currently free */
|
||||
uint32_t timeStamp;
|
||||
void *pCaller;
|
||||
}blockTracking_t;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/*Header description for buffers.*/
|
||||
typedef struct listHeader_tag
|
||||
{
|
||||
listElement_t link;
|
||||
struct pools_tag *pParentPool;
|
||||
}listHeader_t;
|
||||
|
||||
/*Buffer pools. Used by most functions*/
|
||||
typedef struct pools_tag
|
||||
{
|
||||
list_t anchor; /* MUST be first element in pools_t struct */
|
||||
uint16_t nextBlockSize;
|
||||
uint16_t blockSize;
|
||||
uint16_t poolId;
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStat_t poolStatistics;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
uint8_t numBlocks;
|
||||
uint8_t allocatedBlocks;
|
||||
}pools_t;
|
||||
|
||||
/*Buffer pool description. Used by MM_Init() for creating the buffer pools. */
|
||||
typedef struct poolInfo_tag
|
||||
{
|
||||
uint16_t blockSize;
|
||||
uint16_t poolSize;
|
||||
uint16_t poolId;
|
||||
uint8_t padding[2];
|
||||
}poolInfo_t;
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize, void *pCaller);
|
||||
uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size);
|
||||
void MEM_CheckIfMemBuffersAreFreed(void);
|
||||
|
||||
/* The timestamp function used by MEM Manager for debug purpose.
|
||||
The timestamp must be in milliseconds! */
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
extern __weak uint32_t MEM_GetTimeStamp(void);
|
||||
#elif defined(__GNUC__)
|
||||
extern __attribute__((weak)) uint32_t MEM_GetTimeStamp(void);
|
||||
#endif
|
||||
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
#endif /* _MEM_MANAGER_H_ */
|
||||
Vendored
Executable
+815
@@ -0,0 +1,815 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the Memory Manager.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#include "Panic.h"
|
||||
#include "MemManager.h"
|
||||
#include "FunctionLib.h"
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#define _block_size_ {
|
||||
#define _number_of_blocks_ ,
|
||||
#define _pool_id_(a) , a ,
|
||||
#define _eol_ },
|
||||
|
||||
|
||||
poolInfo_t poolInfo[] =
|
||||
{
|
||||
PoolsDetails_c
|
||||
{0, 0, 0} /*termination tag*/
|
||||
};
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#define _block_size_ (sizeof(listHeader_t)+
|
||||
#define _number_of_blocks_ ) *
|
||||
#define _eol_ +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define heapSize_c (PoolsDetails_c 0)
|
||||
|
||||
/* Heap */
|
||||
uint32_t memHeap[heapSize_c/sizeof(uint32_t)];
|
||||
const uint32_t heapSize = heapSize_c;
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#define _block_size_ 0 *
|
||||
#define _number_of_blocks_ + 0 *
|
||||
#define _eol_ + 1 +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define poolCount (PoolsDetails_c 0)
|
||||
|
||||
/* Memory pool info and anchors. */
|
||||
pools_t memPools[poolCount];
|
||||
#ifdef MEM_STATISTICS
|
||||
pools_t memPoolsSnapShot[poolCount];
|
||||
#endif
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
|
||||
#ifndef NUM_OF_TRACK_PTR
|
||||
#define NUM_OF_TRACK_PTR 1
|
||||
#endif
|
||||
|
||||
#define _block_size_ 0*
|
||||
#define _number_of_blocks_ +
|
||||
#define _eol_ +
|
||||
#define _pool_id_(a)
|
||||
|
||||
#define mTotalNoOfMsgs_d (PoolsDetails_c 0)
|
||||
static const uint16_t mTotalNoOfMsgs_c = mTotalNoOfMsgs_d;
|
||||
blockTracking_t memTrack[mTotalNoOfMsgs_d];
|
||||
|
||||
#undef _block_size_
|
||||
#undef _number_of_blocks_
|
||||
#undef _eol_
|
||||
#undef _pool_id_
|
||||
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/* Free messages counter. Not used by module. */
|
||||
uint16_t gFreeMessagesCount;
|
||||
#ifdef MEM_STATISTICS
|
||||
uint16_t gFreeMessagesCountMin = 0xFFFF;
|
||||
uint16_t gTotalFragmentWaste = 0;
|
||||
uint16_t gMaxTotalFragmentWaste = 0;
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function initializes the message module private variables.
|
||||
* Must be called at boot time, or if device is reset.
|
||||
*
|
||||
* \param[in] none
|
||||
*
|
||||
* \return MEM_SUCCESS_c if initialization is successful. (It's always successful).
|
||||
*
|
||||
********************************************************************************** */
|
||||
memStatus_t MEM_Init(void)
|
||||
{
|
||||
poolInfo_t *pPoolInfo = poolInfo; /* IN: Memory layout information */
|
||||
pools_t *pPools = memPools;/* OUT: Will be initialized with requested memory pools. */
|
||||
uint8_t *pHeap = (uint8_t *)memHeap;/* IN: Memory heap.*/
|
||||
|
||||
uint16_t poolN;
|
||||
#ifdef MEM_TRACKING
|
||||
uint16_t memTrackIndex = 0;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
gFreeMessagesCount = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
poolN = pPoolInfo->poolSize;
|
||||
ListInit((listHandle_t)&pPools->anchor, poolN);
|
||||
#ifdef MEM_STATISTICS
|
||||
pPools->poolStatistics.numBlocks = 0;
|
||||
pPools->poolStatistics.allocatedBlocks = 0;
|
||||
pPools->poolStatistics.allocatedBlocksPeak = 0;
|
||||
pPools->poolStatistics.allocationFailures = 0;
|
||||
pPools->poolStatistics.freeFailures = 0;
|
||||
#ifdef MEM_TRACKING
|
||||
pPools->poolStatistics.poolFragmentWaste = 0;
|
||||
pPools->poolStatistics.poolFragmentWastePeak = 0;
|
||||
pPools->poolStatistics.poolFragmentMinWaste = 0xFFFF;
|
||||
pPools->poolStatistics.poolFragmentMaxWaste = 0;
|
||||
#endif /*MEM_TRACKING*/
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
while(poolN)
|
||||
{
|
||||
/* Add block to list of free memory. */
|
||||
ListAddTail((listHandle_t)&pPools->anchor, (listElementHandle_t)&((listHeader_t *)pHeap)->link);
|
||||
((listHeader_t *)pHeap)->pParentPool = pPools;
|
||||
#ifdef MEM_STATISTICS
|
||||
pPools->poolStatistics.numBlocks++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
pPools->numBlocks++;
|
||||
gFreeMessagesCount++;
|
||||
#ifdef MEM_TRACKING
|
||||
memTrack[memTrackIndex].blockAddr = (void *)(pHeap + sizeof(listHeader_t));
|
||||
memTrack[memTrackIndex].blockSize = pPoolInfo->blockSize;
|
||||
memTrack[memTrackIndex].fragmentWaste = 0;
|
||||
memTrack[memTrackIndex].allocAddr = NULL;
|
||||
memTrack[memTrackIndex].allocCounter = 0;
|
||||
memTrack[memTrackIndex].allocStatus = MEM_TRACKING_FREE_c;
|
||||
memTrack[memTrackIndex].freeAddr = NULL;
|
||||
memTrack[memTrackIndex].freeCounter = 0;
|
||||
memTrackIndex++;
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
/* Add block size (without list header)*/
|
||||
pHeap += pPoolInfo->blockSize + sizeof(listHeader_t);
|
||||
poolN--;
|
||||
}
|
||||
|
||||
pPools->blockSize = pPoolInfo->blockSize;
|
||||
pPools->poolId = pPoolInfo->poolId;
|
||||
pPools->nextBlockSize = (pPoolInfo+1)->blockSize;
|
||||
if(pPools->nextBlockSize == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pPools++;
|
||||
pPoolInfo++;
|
||||
}
|
||||
|
||||
return MEM_SUCCESS_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function returns the number of available blocks greater or
|
||||
* equal to the given size.
|
||||
*
|
||||
* \param[in] size - Size of blocks to check for availability.
|
||||
*
|
||||
* \return Number of available blocks greater or equal to the given size.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint32_t MEM_GetAvailableBlocks
|
||||
(
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
pools_t *pPools = memPools;
|
||||
uint32_t pTotalCount = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(size <= pPools->blockSize)
|
||||
{
|
||||
pTotalCount += ListGetSize((listHandle_t)&pPools->anchor);
|
||||
}
|
||||
|
||||
if(pPools->nextBlockSize == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pPools++;
|
||||
}
|
||||
|
||||
return pTotalCount;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Allocate a block from the memory pools. The function uses the
|
||||
* numBytes argument to look up a pool with adequate block sizes.
|
||||
* \param[in] numBytes - Size of buffer to allocate.
|
||||
*
|
||||
* \return Pointer to the allocated buffer, NULL if failed.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Allocate a block from the memory pools. The function uses the
|
||||
* numBytes argument to look up a pool with adequate block sizes.
|
||||
* \param[in] numBytes - Size of buffer to allocate.
|
||||
* \param[in] poolId - The ID of the pool where to search for a free buffer.
|
||||
* \param[in] pCaller - pointer to the caller function (Debug purpose)
|
||||
*
|
||||
* \return Pointer to the allocated buffer, NULL if failed.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
void* MEM_BufferAllocWithId
|
||||
(
|
||||
uint32_t numBytes,
|
||||
uint8_t poolId,
|
||||
void *pCaller
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif
|
||||
#if defined(MEM_TRACKING) || defined(MEM_DEBUG_OUT_OF_MEMORY)
|
||||
uint16_t requestedSize = numBytes;
|
||||
#endif /*MEM_TRACKING*/
|
||||
#ifdef MEM_STATISTICS
|
||||
bool_t allocFailure = FALSE;
|
||||
#endif
|
||||
|
||||
pools_t *pPools = memPools;
|
||||
listHeader_t *pBlock;
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
while(numBytes)
|
||||
{
|
||||
if( (numBytes <= pPools->blockSize) && (poolId == pPools->poolId) )
|
||||
{
|
||||
pBlock = (listHeader_t *)ListRemoveHead((listHandle_t)&pPools->anchor);
|
||||
|
||||
if(NULL != pBlock)
|
||||
{
|
||||
pBlock++;
|
||||
gFreeMessagesCount--;
|
||||
pPools->allocatedBlocks++;
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
if(gFreeMessagesCount < gFreeMessagesCountMin)
|
||||
{
|
||||
gFreeMessagesCountMin = gFreeMessagesCount;
|
||||
}
|
||||
|
||||
pPools->poolStatistics.allocatedBlocks++;
|
||||
if ( pPools->poolStatistics.allocatedBlocks > pPools->poolStatistics.allocatedBlocksPeak )
|
||||
{
|
||||
pPools->poolStatistics.allocatedBlocksPeak = pPools->poolStatistics.allocatedBlocks;
|
||||
}
|
||||
MEM_ASSERT(pPools->poolStatistics.allocatedBlocks <= pPools->poolStatistics.numBlocks);
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
MEM_Track(pBlock, MEM_TRACKING_ALLOC_c, savedLR, requestedSize, pCaller);
|
||||
#endif /*MEM_TRACKING*/
|
||||
OSA_InterruptEnable();
|
||||
return pBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MEM_STATISTICS
|
||||
if(!allocFailure)
|
||||
{
|
||||
pPools->poolStatistics.allocationFailures++;
|
||||
allocFailure = TRUE;
|
||||
}
|
||||
#endif /*MEM_STATISTICS*/
|
||||
if(numBytes > pPools->nextBlockSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* No more blocks of that size, try next size. */
|
||||
numBytes = pPools->nextBlockSize;
|
||||
}
|
||||
}
|
||||
/* Try next pool*/
|
||||
if(pPools->nextBlockSize)
|
||||
{
|
||||
pPools++;
|
||||
}
|
||||
else
|
||||
{
|
||||
numBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEM_DEBUG_OUT_OF_MEMORY
|
||||
if (requestedSize)
|
||||
{
|
||||
panic( 0, (uint32_t)MEM_BufferAllocWithId, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
OSA_InterruptEnable();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Deallocate a memory block by putting it in the corresponding pool
|
||||
* of free blocks.
|
||||
*
|
||||
* \param[in] buffer - Pointer to buffer to deallocate.
|
||||
*
|
||||
* \return MEM_SUCCESS_c if deallocation was successful, MEM_FREE_ERROR_c if not.
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
* \remarks Never deallocate the same buffer twice.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#if (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX))
|
||||
#if defined MULTICORE_HOST
|
||||
memStatus_t MEM_BufferFreeOnMaster
|
||||
#elif defined MULTICORE_BLACKBOX
|
||||
memStatus_t MEM_BufferFreeOnSlave
|
||||
#endif /* MULTICORE_HOST */
|
||||
(
|
||||
uint8_t *pBuff
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif /*MEM_TRACKING*/
|
||||
listHeader_t *pHeader;
|
||||
|
||||
if( pBuff == NULL )
|
||||
{
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
pHeader = (listHeader_t *)pBuff-1;
|
||||
|
||||
if( ((uint8_t*)pHeader < (uint8_t*)memHeap) || ((uint8_t*)pHeader > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MEM_BufferFree(pBuff);
|
||||
}
|
||||
}
|
||||
#endif /* (defined MULTICORE_MEM_MANAGER) && ((defined MULTICORE_HOST) || (defined MULTICORE_BLACKBOX)) */
|
||||
|
||||
memStatus_t MEM_BufferFree
|
||||
(
|
||||
void* buffer /* IN: Block of memory to free*/
|
||||
)
|
||||
{
|
||||
#ifdef MEM_TRACKING
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = (uint32_t) __get_LR();
|
||||
#endif /*MEM_TRACKING*/
|
||||
listHeader_t *pHeader;
|
||||
pools_t *pParentPool;
|
||||
pools_t *pool;
|
||||
|
||||
if( buffer == NULL )
|
||||
{
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
pHeader = (listHeader_t *)buffer-1;
|
||||
|
||||
if( ((uint8_t*)pHeader < (uint8_t*)memHeap) || ((uint8_t*)pHeader > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
#if (defined MULTICORE_MEM_MANAGER) && (defined MULTICORE_BLACKBOX)
|
||||
return MEM_BufferFreeOnMaster(buffer);
|
||||
#elif (defined MULTICORE_MEM_MANAGER) && (defined MULTICORE_HOST)
|
||||
return MEM_BufferFreeOnSlave(buffer);
|
||||
#else
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
#endif
|
||||
}
|
||||
|
||||
OSA_InterruptDisable();
|
||||
|
||||
pParentPool = (pools_t *)pHeader->pParentPool;
|
||||
pool = memPools;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (pParentPool == pool)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(pool->nextBlockSize == 0)
|
||||
{
|
||||
/* The parent pool was not found! This means that the memory buffer is corrupt or
|
||||
that the MEM_BufferFree() function was called with an invalid parameter */
|
||||
#ifdef MEM_STATISTICS
|
||||
pParentPool->poolStatistics.freeFailures++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
OSA_InterruptEnable();
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
pool++;
|
||||
}
|
||||
|
||||
if( pHeader->link.list != NULL )
|
||||
{
|
||||
/* The memory buffer appears to be enqueued in a linked list.
|
||||
This list may be the free memory buffers pool, or another list. */
|
||||
#ifdef MEM_STATISTICS
|
||||
pParentPool->poolStatistics.freeFailures++;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
OSA_InterruptEnable();
|
||||
#ifdef MEM_DEBUG_INVALID_POINTERS
|
||||
panic( 0, (uint32_t)MEM_BufferFree, 0, 0);
|
||||
#endif
|
||||
return MEM_FREE_ERROR_c;
|
||||
}
|
||||
|
||||
gFreeMessagesCount++;
|
||||
|
||||
ListAddTail((listHandle_t)&pParentPool->anchor, (listElementHandle_t)&pHeader->link);
|
||||
pParentPool->allocatedBlocks--;
|
||||
|
||||
#ifdef MEM_STATISTICS
|
||||
MEM_ASSERT(pParentPool->poolStatistics.allocatedBlocks > 0);
|
||||
pParentPool->poolStatistics.allocatedBlocks--;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
#ifdef MEM_TRACKING
|
||||
MEM_Track(buffer, MEM_TRACKING_FREE_c, savedLR, 0, NULL);
|
||||
#endif /*MEM_TRACKING*/
|
||||
OSA_InterruptEnable();
|
||||
return MEM_SUCCESS_c;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Determines the size of a memory block
|
||||
*
|
||||
* \param[in] buffer - Pointer to buffer.
|
||||
*
|
||||
* \return size of memory block
|
||||
*
|
||||
* \pre Memory manager must be previously initialized.
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint16_t MEM_BufferGetSize
|
||||
(
|
||||
void* buffer /* IN: Block of memory to free*/
|
||||
)
|
||||
{
|
||||
if( buffer )
|
||||
{
|
||||
return ((pools_t *)((listHeader_t *)buffer-1)->pParentPool)->blockSize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! *********************************************************************************
|
||||
* \brief This function updates the tracking array element corresponding to the given
|
||||
* block.
|
||||
*
|
||||
* \param[in] block - Pointer to the block.
|
||||
* \param[in] alloc - Indicates whether an allocation or free operation was performed
|
||||
* \param[in] address - Address where MEM_BufferAlloc or MEM_BufferFree was called
|
||||
* \param[in] requestedSize - Indicates the requested buffer size passed to MEM_BufferAlloc.
|
||||
* Has no use if a free operation was performed.
|
||||
*
|
||||
* \return Returns TRUE if correct allocation or dealocation was performed, FALSE if a
|
||||
* buffer was allocated or freed twice.
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize, void *pCaller)
|
||||
{
|
||||
uint16_t i;
|
||||
blockTracking_t *pTrack = NULL;
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStat_t * poolStatistics = (poolStat_t *)&((pools_t *)( (listElementHandle_t)(block-1)->pParentPool ))->poolStatistics;
|
||||
#endif
|
||||
|
||||
for( i=0; i<mTotalNoOfMsgs_c; i++ )
|
||||
{
|
||||
if( block == memTrack[i].blockAddr )
|
||||
{
|
||||
pTrack = &memTrack[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !pTrack || pTrack->allocStatus == alloc)
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic( 0, (uint32_t)MEM_Track, 0, 0);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pTrack->allocStatus = alloc;
|
||||
pTrack->pCaller = (void*)((uint32_t)pCaller & 0x7FFFFFFF);
|
||||
|
||||
if(alloc == MEM_TRACKING_ALLOC_c)
|
||||
{
|
||||
pTrack->fragmentWaste = pTrack->blockSize - requestedSize;
|
||||
pTrack->allocCounter++;
|
||||
pTrack->allocAddr = (void *)address;
|
||||
if( (uint32_t)pCaller & 0x80000000 )
|
||||
{
|
||||
pTrack->timeStamp = 0xFFFFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTrack->timeStamp = MEM_GetTimeStamp();
|
||||
}
|
||||
#ifdef MEM_STATISTICS
|
||||
gTotalFragmentWaste += pTrack->fragmentWaste;
|
||||
if(gTotalFragmentWaste > gMaxTotalFragmentWaste)
|
||||
{
|
||||
gMaxTotalFragmentWaste = gTotalFragmentWaste;
|
||||
FLib_MemCpy(&memPoolsSnapShot[0], &memPools[0], sizeof(memPools));
|
||||
}
|
||||
|
||||
poolStatistics->poolFragmentWaste += pTrack->fragmentWaste;
|
||||
if(poolStatistics->poolFragmentWaste > poolStatistics->poolFragmentWastePeak)
|
||||
poolStatistics->poolFragmentWastePeak = poolStatistics->poolFragmentWaste;
|
||||
if(pTrack->fragmentWaste < poolStatistics->poolFragmentMinWaste)
|
||||
{
|
||||
poolStatistics->poolFragmentMinWaste = pTrack->fragmentWaste;
|
||||
}
|
||||
if(pTrack->fragmentWaste > poolStatistics->poolFragmentMaxWaste)
|
||||
{
|
||||
poolStatistics->poolFragmentMaxWaste = pTrack->fragmentWaste;
|
||||
}
|
||||
|
||||
if(poolStatistics->allocatedBlocks == poolStatistics->numBlocks)
|
||||
{
|
||||
//__asm("BKPT #0\n") ; /* cause the debugger to stop */
|
||||
}
|
||||
#endif /*MEM_STATISTICS*/
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MEM_STATISTICS
|
||||
poolStatistics->poolFragmentWaste -= pTrack->fragmentWaste;
|
||||
gTotalFragmentWaste -= pTrack->fragmentWaste;
|
||||
#endif /*MEM_STATISTICS*/
|
||||
|
||||
pTrack->fragmentWaste = 0;
|
||||
pTrack->freeCounter++;
|
||||
pTrack->freeAddr = (void *)address;
|
||||
pTrack->timeStamp = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function checks for buffer overflow when copying multiple bytes
|
||||
*
|
||||
* \param[in] p - pointer to destination.
|
||||
* \param[in] size - number of bytes to copy
|
||||
*
|
||||
* \return 1 if overflow detected, else 0
|
||||
*
|
||||
********************************************************************************** */
|
||||
uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size)
|
||||
{
|
||||
poolInfo_t *pPollInfo = poolInfo;
|
||||
uint8_t* memAddr = (uint8_t *)memHeap;
|
||||
uint32_t poolBytes, blockBytes, i;
|
||||
|
||||
if( (p < (uint8_t*)memHeap) || (p > ((uint8_t*)memHeap + sizeof(memHeap))) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while( pPollInfo->blockSize )
|
||||
{
|
||||
blockBytes = pPollInfo->blockSize + sizeof(listHeader_t);
|
||||
poolBytes = blockBytes * pPollInfo->poolSize;
|
||||
|
||||
/* Find the correct message pool */
|
||||
if( (p >= memAddr) && (p < memAddr + poolBytes) )
|
||||
{
|
||||
/* Check if the size to copy is greather then the size of the current block */
|
||||
if( size > pPollInfo->blockSize )
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic(0,0,0,0);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the correct memory block */
|
||||
for( i=0; i<pPollInfo->poolSize; i++ )
|
||||
{
|
||||
if( (p >= memAddr) && (p < memAddr + blockBytes) )
|
||||
{
|
||||
if( p + size > memAddr + blockBytes )
|
||||
{
|
||||
#ifdef MEM_DEBUG
|
||||
panic(0,0,0,0);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memAddr += blockBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* check next pool */
|
||||
memAddr += poolBytes;
|
||||
pPollInfo++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function checks if the buffers are allocated for more than the
|
||||
* specified duration
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
void MEM_CheckIfMemBuffersAreFreed(void)
|
||||
{
|
||||
uint32_t t;
|
||||
uint16_t i, j = 0;
|
||||
uint8_t trackCount = 0;
|
||||
pools_t *pParentPool;
|
||||
volatile blockTracking_t *pTrack;
|
||||
static volatile blockTracking_t *mpTrackTbl[NUM_OF_TRACK_PTR];
|
||||
static uint32_t lastTimestamp = 0;
|
||||
uint32_t currentTime = MEM_GetTimeStamp();
|
||||
|
||||
if( (currentTime - lastTimestamp) >= MEM_CheckMemBufferInterval_c )
|
||||
{
|
||||
lastTimestamp = currentTime;
|
||||
j = 0;
|
||||
|
||||
for( i = 0; i < mTotalNoOfMsgs_c; i++ )
|
||||
{
|
||||
pTrack = &memTrack[i];
|
||||
|
||||
/* Validate the pParent first */
|
||||
pParentPool = (((listHeader_t *)(pTrack->blockAddr))-1)->pParentPool;
|
||||
if(pParentPool != &memPools[j])
|
||||
{
|
||||
if(j < NumberOfElements(memPools))
|
||||
{
|
||||
j++;
|
||||
if(pParentPool != &memPools[j])
|
||||
{
|
||||
panic(0,0,0,0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
panic(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if it should be freed */
|
||||
OSA_InterruptDisable();
|
||||
if((pTrack->timeStamp != 0xffffffff ) &&
|
||||
(pTrack->allocStatus == MEM_TRACKING_ALLOC_c) &&
|
||||
(currentTime > pTrack->timeStamp))
|
||||
{
|
||||
t = currentTime - pTrack->timeStamp;
|
||||
if( t > MEM_CheckMemBufferThreshold_c )
|
||||
{
|
||||
mpTrackTbl[trackCount++] = pTrack;
|
||||
if(trackCount == NUM_OF_TRACK_PTR)
|
||||
{
|
||||
(void)mpTrackTbl; /* remove compiler warnings */
|
||||
panic(0,0,0,0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
OSA_InterruptEnable();
|
||||
} /* end for */
|
||||
}
|
||||
}
|
||||
#endif /*MEM_TRACKING*/
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief Get time-stamp for memory operation: alloc/free.
|
||||
*
|
||||
* \return dymmy time-stamp
|
||||
*
|
||||
********************************************************************************** */
|
||||
#ifdef MEM_TRACKING
|
||||
#if defined(__IAR_SYSTEMS_ICC__)
|
||||
__weak uint32_t MEM_GetTimeStamp(void)
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__((weak)) uint32_t MEM_GetTimeStamp(void)
|
||||
#endif
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
#endif /* MEM_TRACKING */
|
||||
|
||||
|
||||
/*! ************************************************************************************************
|
||||
\brief MEM Manager calloc alternative implementation.
|
||||
|
||||
\param [in] len Number of blocks
|
||||
\param [in] size Size of one block
|
||||
|
||||
\return void* Pointer to the allocated buffer or NULL in case of error
|
||||
************************************************************************************************* */
|
||||
void* MEM_CallocAlt
|
||||
(
|
||||
size_t len,
|
||||
size_t val
|
||||
)
|
||||
{
|
||||
void *pData = MEM_BufferAllocForever (len* val, 0);
|
||||
if (pData)
|
||||
{
|
||||
FLib_MemSet (pData, 0, len* val);
|
||||
}
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
/*! ************************************************************************************************
|
||||
\brief MEM Manager free alternative implementation.
|
||||
|
||||
\param [in] pData Pointer to the allocated buffer
|
||||
|
||||
\return void
|
||||
************************************************************************************************* */
|
||||
void MEM_FreeAlt
|
||||
(
|
||||
void* pData
|
||||
)
|
||||
{
|
||||
MEM_BufferFree (pData);
|
||||
}
|
||||
Vendored
Executable
+612
@@ -0,0 +1,612 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
#ifndef _FSL_OS_ABSTRACTION_H_
|
||||
#define _FSL_OS_ABSTRACTION_H_
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
#include "fsl_os_abstraction_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*! @brief Type for the Task Priority*/
|
||||
typedef uint16_t osaTaskPriority_t;
|
||||
/*! @brief Type for the timer definition*/
|
||||
typedef enum {
|
||||
osaTimer_Once = 0, /*!< one-shot timer*/
|
||||
osaTimer_Periodic = 1 /*!< repeating timer*/
|
||||
} osaTimer_t;
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
|
||||
typedef void* osaTaskId_t;
|
||||
/*! @brief Type for the parameter to be passed to the task at its creation */
|
||||
typedef void* osaTaskParam_t;
|
||||
/*! @brief Type for task pointer. Task prototype declaration */
|
||||
typedef void (*osaTaskPtr_t) (osaTaskParam_t task_param);
|
||||
/*! @brief Type for the semaphore handler, returned by the OSA_SemaphoreCreate function. */
|
||||
typedef void* osaSemaphoreId_t;
|
||||
/*! @brief Type for the mutex handler, returned by the OSA_MutexCreate function. */
|
||||
typedef void* osaMutexId_t;
|
||||
/*! @brief Type for the event handler, returned by the OSA_EventCreate function. */
|
||||
typedef void* osaEventId_t;
|
||||
/*! @brief Type for an event flags group, bit 32 is reserved. */
|
||||
typedef uint32_t osaEventFlags_t;
|
||||
/*! @brief Message definition. */
|
||||
typedef void* osaMsg_t;
|
||||
/*! @brief Type for the message queue handler, returned by the OSA_MsgQCreate function. */
|
||||
typedef void* osaMsgQId_t;
|
||||
/*! @brief Type for the Timer handler, returned by the OSA_TimerCreate function. */
|
||||
typedef void *osaTimerId_t;
|
||||
/*! @brief Type for the Timer callback function pointer. */
|
||||
typedef void (*osaTimerFctPtr_t) (void const *argument);
|
||||
/*! @brief Thread Definition structure contains startup information of a thread.*/
|
||||
typedef struct osaThreadDef_tag {
|
||||
osaTaskPtr_t pthread; /*!< start address of thread function*/
|
||||
uint32_t tpriority; /*!< initial thread priority*/
|
||||
uint32_t instances; /*!< maximum number of instances of that thread function*/
|
||||
uint32_t stacksize; /*!< stack size requirements in bytes; 0 is default stack size*/
|
||||
uint32_t *tstack;
|
||||
void *tlink;
|
||||
uint8_t *tname;
|
||||
bool_t useFloat;
|
||||
} osaThreadDef_t;
|
||||
/*! @brief Thread Link Definition structure .*/
|
||||
typedef struct osaThreadLink_tag{
|
||||
uint8_t link[12];
|
||||
osaTaskId_t osThreadId;
|
||||
osaThreadDef_t *osThreadDefHandle;
|
||||
uint32_t *osThreadStackHandle;
|
||||
}osaThreadLink_t, *osaThreadLinkHandle_t;
|
||||
|
||||
/*! @Timer Definition structure contains timer parameters.*/
|
||||
typedef struct osaTimerDef_tag {
|
||||
osaTimerFctPtr_t pfCallback; /* < start address of a timer function */
|
||||
void *argument;
|
||||
} osaTimerDef_t;
|
||||
/*! @brief Defines the return status of OSA's functions */
|
||||
typedef enum osaStatus_tag
|
||||
{
|
||||
osaStatus_Success = 0U, /*!< Success */
|
||||
osaStatus_Error = 1U, /*!< Failed */
|
||||
osaStatus_Timeout = 2U, /*!< Timeout occurs while waiting */
|
||||
osaStatus_Idle = 3U /*!< Used for bare metal only, the wait object is not ready
|
||||
and timeout still not occur */
|
||||
}osaStatus_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if defined (FSL_RTOS_MQX)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_FREE_RTOS)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_UCOSII)
|
||||
#define USE_RTOS 1
|
||||
#elif defined (FSL_RTOS_UCOSIII)
|
||||
#define USE_RTOS 1
|
||||
#else
|
||||
#define USE_RTOS 0
|
||||
#endif
|
||||
|
||||
#define OSA_PRIORITY_IDLE (6)
|
||||
#define OSA_PRIORITY_LOW (5)
|
||||
#define OSA_PRIORITY_BELOW_NORMAL (4)
|
||||
#define OSA_PRIORITY_NORMAL (3)
|
||||
#define OSA_PRIORITY_ABOVE_NORMAL (2)
|
||||
#define OSA_PRIORITY_HIGH (1)
|
||||
#define OSA_PRIORITY_REAL_TIME (0)
|
||||
#define OSA_TASK_PRIORITY_MAX (0)
|
||||
#define OSA_TASK_PRIORITY_MIN (15)
|
||||
#define SIZE_IN_UINT32_UNITS(size) (((size) + sizeof(uint32_t) - 1) / sizeof(uint32_t))
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define osaWaitForever_c ((uint32_t)(-1))
|
||||
#define osaEventFlagsAll_c ((osaEventFlags_t)(0x00FFFFFF))
|
||||
#define osThreadStackArray(name) osThread_##name##_stack
|
||||
#define osThreadStackDef(name, stacksize, instances) \
|
||||
uint32_t osThreadStackArray(name)[SIZE_IN_UINT32_UNITS(stacksize)*(instances)];
|
||||
|
||||
/* ==== Thread Management ==== */
|
||||
|
||||
/* Create a Thread Definition with function, priority, and stack requirements.
|
||||
* \param name name of the thread function.
|
||||
* \param priority initial priority of the thread function.
|
||||
* \param instances number of possible thread instances.
|
||||
* \param stackSz stack size (in bytes) requirements for the thread function.
|
||||
* \param useFloat
|
||||
*/
|
||||
#if defined(FSL_RTOS_MQX)
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
osThreadLink_##name, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#elif defined (FSL_RTOS_UCOSII)
|
||||
#if gTaskMultipleInstancesManagement_c
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadLink_t osThreadLink_##name[instances] = {0}; \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
osThreadLink_##name, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#else
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osThreadStackDef(name, stackSz, instances) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
osThreadStackArray(name), \
|
||||
NULL, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#endif
|
||||
#else
|
||||
#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \
|
||||
osaThreadDef_t os_thread_def_##name = { (name), \
|
||||
(priority), \
|
||||
(instances), \
|
||||
(stackSz), \
|
||||
NULL, \
|
||||
NULL, \
|
||||
(uint8_t*) #name,\
|
||||
(useFloat)}
|
||||
#endif
|
||||
/* Access a Thread defintion.
|
||||
* \param name name of the thread definition object.
|
||||
*/
|
||||
#define OSA_TASK(name) \
|
||||
&os_thread_def_##name
|
||||
|
||||
#define OSA_TASK_PROTO(name) \
|
||||
extern osaThreadDef_t os_thread_def_##name
|
||||
/* ==== Timer Management ====
|
||||
* Define a Timer object.
|
||||
* \param name name of the timer object.
|
||||
* \param function name of the timer call back function.
|
||||
*/
|
||||
|
||||
#define OSA_TIMER_DEF(name, function) \
|
||||
osaTimerDef_t os_timer_def_##name = \
|
||||
{ (function), NULL }
|
||||
|
||||
/* Access a Timer definition.
|
||||
* \param name name of the timer object.
|
||||
*/
|
||||
#define OSA_TIMER(name) \
|
||||
&os_timer_def_##name
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
******************************************************************************
|
||||
* Public memory declarations
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
extern const uint8_t gUseRtos_c;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
/*!
|
||||
* @name Task management
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Creates a task.
|
||||
*
|
||||
* This function is used to create task based on the resources defined
|
||||
* by the macro OSA_TASK_DEFINE.
|
||||
*
|
||||
* @param thread_def pointer to the osaThreadDef_t structure which defines the task.
|
||||
* @param task_param Pointer to be passed to the task when it is created.
|
||||
*
|
||||
* @retval taskId The task is successfully created.
|
||||
* @retval NULL The task can not be created..
|
||||
*
|
||||
* Example:
|
||||
@code
|
||||
osaTaskId_t taskId;
|
||||
OSA_TASK_DEFINE( Job1, OSA_PRIORITY_HIGH, 1, 800, 0);;
|
||||
taskId = OSA__TaskCreate(OSA__TASK(Job1), (osaTaskParam_t)NULL);
|
||||
@endcode
|
||||
*/
|
||||
osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def, osaTaskParam_t task_param);
|
||||
|
||||
/*!
|
||||
* @brief Gets the handler of active task.
|
||||
*
|
||||
* @return Handler to current active task.
|
||||
*/
|
||||
osaTaskId_t OSA_TaskGetId(void);
|
||||
|
||||
/*!
|
||||
* @brief Puts the active task to the end of scheduler's queue.
|
||||
*
|
||||
* When a task calls this function, it gives up the CPU and puts itself to the
|
||||
* end of a task ready list.
|
||||
*
|
||||
* @retval osaStatus_Success The function is called successfully.
|
||||
* @retval osaStatus_Error Error occurs with this function.
|
||||
*/
|
||||
osaStatus_t OSA_TaskYield(void);
|
||||
|
||||
/*!
|
||||
* @brief Gets the priority of a task.
|
||||
*
|
||||
* @param taskId The handler of the task whose priority is received.
|
||||
*
|
||||
* @return Task's priority.
|
||||
*/
|
||||
osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId);
|
||||
|
||||
/*!
|
||||
* @brief Sets the priority of a task.
|
||||
*
|
||||
* @param taskId The handler of the task whose priority is set.
|
||||
* @param taskPriority The priority to set.
|
||||
*
|
||||
* @retval osaStatus_Success Task's priority is set successfully.
|
||||
* @retval osaStatus_Error Task's priority can not be set.
|
||||
*/
|
||||
osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority);
|
||||
/*!
|
||||
* @brief Destroys a previously created task.
|
||||
*
|
||||
* @param taskId The handler of the task to destroy. Returned by the OSA_TaskCreate function.
|
||||
*
|
||||
* @retval osaStatus_Success The task was successfully destroyed.
|
||||
* @retval osaStatus_Error Task destruction failed or invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId);
|
||||
|
||||
/*!
|
||||
* @brief Creates a semaphore with a given value.
|
||||
*
|
||||
* This function creates a semaphore and sets the value to the parameter
|
||||
* initValue.
|
||||
*
|
||||
* @param initValue Initial value the semaphore will be set to.
|
||||
*
|
||||
* @retval handler to the new semaphore if the semaphore is created successfully.
|
||||
* @retval NULL if the semaphore can not be created.
|
||||
*
|
||||
*
|
||||
*/
|
||||
osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created semaphore.
|
||||
*
|
||||
* @param semId Pointer to the semaphore to destroy.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is successfully destroyed.
|
||||
* @retval osaStatus_Error The semaphore can not be destroyed.
|
||||
*/
|
||||
osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId);
|
||||
|
||||
/*!
|
||||
* @brief Pending a semaphore with timeout.
|
||||
*
|
||||
* This function checks the semaphore's counting value. If it is positive,
|
||||
* decreases it and returns osaStatus_Success. Otherwise, a timeout is used
|
||||
* to wait.
|
||||
*
|
||||
* @param semId Pointer to the semaphore.
|
||||
* @param millisec The maximum number of milliseconds to wait if semaphore is not
|
||||
* positive. Pass osaWaitForever_c to wait indefinitely, pass 0
|
||||
* will return osaStatus_Timeout immediately.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is received.
|
||||
* @retval osaStatus_Timeout The semaphore is not received within the specified 'timeout'.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Signals for someone waiting on the semaphore to wake up.
|
||||
*
|
||||
* Wakes up one task that is waiting on the semaphore. If no task is waiting, increases
|
||||
* the semaphore's counting value.
|
||||
*
|
||||
* @param semId Pointer to the semaphore to signal.
|
||||
*
|
||||
* @retval osaStatus_Success The semaphore is successfully signaled.
|
||||
* @retval osaStatus_Error The object can not be signaled or invalid parameter.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId);
|
||||
|
||||
/*!
|
||||
* @brief Create an unlocked mutex.
|
||||
*
|
||||
* This function creates a non-recursive mutex and sets it to unlocked status.
|
||||
*
|
||||
* @param none.
|
||||
*
|
||||
* @retval handler to the new mutex if the mutex is created successfully.
|
||||
* @retval NULL if the mutex can not be created.
|
||||
*/
|
||||
osaMutexId_t OSA_MutexCreate(void);
|
||||
|
||||
/*!
|
||||
* @brief Waits for a mutex and locks it.
|
||||
*
|
||||
* This function checks the mutex's status. If it is unlocked, locks it and returns the
|
||||
* osaStatus_Success. Otherwise, waits for a timeout in milliseconds to lock.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
* @param millisec The maximum number of milliseconds to wait for the mutex.
|
||||
* If the mutex is locked, Pass the value osaWaitForever_c will
|
||||
* wait indefinitely, pass 0 will return osaStatus_Timeout
|
||||
* immediately.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is locked successfully.
|
||||
* @retval osaStatus_Timeout Timeout occurred.
|
||||
* @retval osaStatus_Error Incorrect parameter was passed.
|
||||
*
|
||||
* @note This is non-recursive mutex, a task can not try to lock the mutex it has locked.
|
||||
*/
|
||||
osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Unlocks a previously locked mutex.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is successfully unlocked.
|
||||
* @retval osaStatus_Error The mutex can not be unlocked or invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created mutex.
|
||||
*
|
||||
* @param mutexId Pointer to the Mutex.
|
||||
*
|
||||
* @retval osaStatus_Success The mutex is successfully destroyed.
|
||||
* @retval osaStatus_Error The mutex can not be destroyed.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId);
|
||||
|
||||
/*!
|
||||
* @brief Initializes an event object with all flags cleared.
|
||||
*
|
||||
* This function creates an event object and set its clear mode. If autoClear
|
||||
* is TRUE, when a task gets the event flags, these flags will be
|
||||
* cleared automatically. Otherwise these flags must
|
||||
* be cleared manually.
|
||||
*
|
||||
* @param autoClear TRUE The event is auto-clear.
|
||||
* FALSE The event manual-clear
|
||||
* @retval handler to the new event if the event is created successfully.
|
||||
* @retval NULL if the event can not be created.
|
||||
*/
|
||||
osaEventId_t OSA_EventCreate(bool_t autoClear);
|
||||
|
||||
/*!
|
||||
* @brief Sets one or more event flags.
|
||||
*
|
||||
* Sets specified flags of an event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToSet Flags to be set.
|
||||
*
|
||||
* @retval osaStatus_Success The flags were successfully set.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet);
|
||||
|
||||
/*!
|
||||
* @brief Clears one or more flags.
|
||||
*
|
||||
* Clears specified flags of an event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToClear Flags to be clear.
|
||||
*
|
||||
* @retval osaStatus_Success The flags were successfully cleared.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear);
|
||||
|
||||
/*!
|
||||
* @brief Waits for specified event flags to be set.
|
||||
*
|
||||
* This function waits for a combination of flags to be set in an event object.
|
||||
* Applications can wait for any/all bits to be set. Also this function could
|
||||
* obtain the flags who wakeup the waiting task.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
* @param flagsToWait Flags that to wait.
|
||||
* @param waitAll Wait all flags or any flag to be set.
|
||||
* @param millisec The maximum number of milliseconds to wait for the event.
|
||||
* If the wait condition is not met, pass osaWaitForever_c will
|
||||
* wait indefinitely, pass 0 will return osaStatus_Timeout
|
||||
* immediately.
|
||||
* @param setFlags Flags that wakeup the waiting task are obtained by this parameter.
|
||||
*
|
||||
* @retval osaStatus_Success The wait condition met and function returns successfully.
|
||||
* @retval osaStatus_Timeout Has not met wait condition within timeout.
|
||||
* @retval osaStatus_Error An incorrect parameter was passed.
|
||||
|
||||
*
|
||||
* @note Please pay attention to the flags bit width, FreeRTOS uses the most
|
||||
* significant 8 bis as control bits, so do not wait these bits while using
|
||||
* FreeRTOS.
|
||||
*
|
||||
*/
|
||||
osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created event object.
|
||||
*
|
||||
* @param eventId Pointer to the event.
|
||||
*
|
||||
* @retval osaStatus_Success The event is successfully destroyed.
|
||||
* @retval osaStatus_Error Event destruction failed.
|
||||
*/
|
||||
osaStatus_t OSA_EventDestroy(osaEventId_t eventId);
|
||||
|
||||
/*!
|
||||
* @brief Initializes a message queue.
|
||||
*
|
||||
* This function allocates memory for and initializes a message queue. Message queue elements are hardcoded as void*.
|
||||
*
|
||||
* @param msgNo :number of messages the message queue should accommodate.
|
||||
* This parameter should not exceed osNumberOfMessages defined in OSAbstractionConfig.h.
|
||||
*
|
||||
* @return: Handler to access the queue for put and get operations. If message queue
|
||||
* creation failed, return NULL.
|
||||
*/
|
||||
osaMsgQId_t OSA_MsgQCreate(uint32_t msgNo);
|
||||
|
||||
/*!
|
||||
* @brief Puts a message at the end of the queue.
|
||||
*
|
||||
* This function puts a message to the end of the message queue. If the queue
|
||||
* is full, this function returns the osaStatus_Error;
|
||||
*
|
||||
* @param msgQId pointer to queue returned by the OSA_MsgQCreate function.
|
||||
* @param pMessage Pointer to the message to be put into the queue.
|
||||
*
|
||||
* @retval osaStatus_Success Message successfully put into the queue.
|
||||
* @retval osaStatus_Error The queue was full or an invalid parameter was passed.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, osaMsg_t pMessage);
|
||||
|
||||
/*!
|
||||
* @brief Reads and remove a message at the head of the queue.
|
||||
*
|
||||
* This function gets a message from the head of the message queue. If the
|
||||
* queue is empty, timeout is used to wait.
|
||||
*
|
||||
* @param msgQId Queue handler returned by the OSA_MsgQCreate function.
|
||||
* @param pMessage Pointer to a memory to save the message.
|
||||
* @param millisec The number of milliseconds to wait for a message. If the
|
||||
* queue is empty, pass osaWaitForever_c will wait indefinitely,
|
||||
* pass 0 will return osaStatus_Timeout immediately.
|
||||
*
|
||||
* @retval osaStatus_Success Message successfully obtained from the queue.
|
||||
* @retval osaStatus_Timeout The queue remains empty after timeout.
|
||||
* @retval osaStatus_Error Invalid parameter.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, osaMsg_t pMessage, uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief Destroys a previously created queue.
|
||||
*
|
||||
* @param msgQId queue handler returned by the OSA_MsgQCreate function.
|
||||
*
|
||||
* @retval osaStatus_Success The queue was successfully destroyed.
|
||||
* @retval osaStatus_Error Message queue destruction failed.
|
||||
*/
|
||||
osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId);
|
||||
|
||||
/*!
|
||||
* @brief Enable all interrupts.
|
||||
*/
|
||||
void OSA_InterruptEnable(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable all interrupts.
|
||||
*/
|
||||
void OSA_InterruptDisable(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable interrupts except high-priority ones
|
||||
*
|
||||
* @param pu8OldIntLevel Variable to hold previous setting
|
||||
*/
|
||||
void OSA_InterruptEnableRestricted(uint32_t *pu32OldIntLevel);
|
||||
|
||||
/*!
|
||||
* @brief Restore interrupts that were previously restricted by a call
|
||||
* to OSA_InterruptEnableRestricted
|
||||
*
|
||||
* @param pu8OldIntLevel Variable holding previous setting
|
||||
*/
|
||||
void OSA_InterruptEnableRestore(uint32_t *pu32OldIntLevel);
|
||||
|
||||
/*!
|
||||
* @brief Enable all interrupts using PRIMASK.
|
||||
*/
|
||||
void OSA_EnableIRQGlobal(void);
|
||||
|
||||
/*!
|
||||
* @brief Disable all interrupts using PRIMASK.
|
||||
*/
|
||||
void OSA_DisableIRQGlobal(void);
|
||||
|
||||
/*!
|
||||
* @brief Delays execution for a number of milliseconds.
|
||||
*
|
||||
* @param millisec The time in milliseconds to wait.
|
||||
*/
|
||||
void OSA_TimeDelay(uint32_t millisec);
|
||||
|
||||
/*!
|
||||
* @brief This function gets current time in milliseconds.
|
||||
*
|
||||
* @retval current time in milliseconds
|
||||
*/
|
||||
uint32_t OSA_TimeGetMsec(void);
|
||||
|
||||
/*!
|
||||
* @brief This function resets the current time to 0.
|
||||
*/
|
||||
void OSA_TimeResetMsec(void);
|
||||
|
||||
/*!
|
||||
* @brief Installs the interrupt handler.
|
||||
*
|
||||
* @param IRQNumber IRQ number of the interrupt.
|
||||
* @param handler The interrupt handler to install.
|
||||
*/
|
||||
void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void));
|
||||
|
||||
/*!
|
||||
* @brief Init the OSA time.
|
||||
*
|
||||
*/
|
||||
void OSA_TimeInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
Executable
+168
@@ -0,0 +1,168 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2013-2014, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
#if !defined(__FSL_OS_ABSTRACTION_BM_H__)
|
||||
#define __FSL_OS_ABSTRACTION_BM_H__
|
||||
|
||||
|
||||
/*!
|
||||
* @addtogroup os_abstraction_bm
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Bare Metal does not use timer. */
|
||||
#define FSL_OSA_BM_TIMER_NONE 0U
|
||||
|
||||
/*! @brief Bare Metal uses SYSTICK as timer. */
|
||||
#define FSL_OSA_BM_TIMER_SYSTICK 1U
|
||||
|
||||
/*! @brief Configure what timer is used in Bare Metal. */
|
||||
#ifndef FSL_OSA_BM_TIMER_CONFIG
|
||||
#define FSL_OSA_BM_TIMER_CONFIG FSL_OSA_BM_TIMER_NONE
|
||||
#endif
|
||||
|
||||
/*! @brief Type for an semaphore */
|
||||
typedef struct Semaphore
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this object */
|
||||
volatile uint8_t semCount; /*!< The count value of the object */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
} semaphore_t;
|
||||
|
||||
/*! @brief Type for a mutex */
|
||||
typedef struct Mutex
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this mutex */
|
||||
volatile bool_t isLocked; /*!< Is the object locked or not */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
} mutex_t;
|
||||
|
||||
/*! @brief Type for task parameter */
|
||||
typedef void* task_param_t;
|
||||
#define gIdleTaskPriority_c ((task_priority_t) 0)
|
||||
#define gInvalidTaskPriority_c ((task_priority_t) -1)
|
||||
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function */
|
||||
typedef void (* task_t)(task_param_t param);
|
||||
/*! @brief Task control block for bare metal. */
|
||||
typedef struct TaskControlBlock
|
||||
{
|
||||
osaTaskPtr_t p_func; /*!< Task's entry */
|
||||
bool_t haveToRun; /*!< Task was signaled */
|
||||
osaTaskPriority_t priority; /*!< Task's priority */
|
||||
osaTaskParam_t param; /*!< Task's parameter */
|
||||
struct TaskControlBlock *next; /*!< Pointer to next task control block */
|
||||
struct TaskControlBlock *prev; /*!< Pointer to previous task control block */
|
||||
} task_control_block_t;
|
||||
|
||||
/*! @brief Type for a task pointer */
|
||||
typedef task_control_block_t* task_handler_t;
|
||||
|
||||
/*! @brief Type for a task stack */
|
||||
typedef uint32_t task_stack_t;
|
||||
/*! @brief Type for an event flags group, bit 32 is reserved */
|
||||
typedef uint32_t event_flags_t;
|
||||
|
||||
|
||||
/*! @brief Type for an event object */
|
||||
typedef struct Event
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout on this event */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
volatile event_flags_t flags; /*!< The flags status */
|
||||
bool_t autoClear; /*!< Auto clear or manual clear */
|
||||
task_handler_t waitingTask; /*!< Handler to the waiting task */
|
||||
} event_t;
|
||||
|
||||
/*! @brief Type for a message queue */
|
||||
typedef struct MsgQueue
|
||||
{
|
||||
volatile bool_t isWaiting; /*!< Is any task waiting for a timeout */
|
||||
uint16_t number; /*!< The number of messages in the queue */
|
||||
uint16_t max; /*!< The max number of queue messages */
|
||||
uint16_t head; /*!< Index of the next message to be read */
|
||||
uint16_t tail; /*!< Index of the next place to write to */
|
||||
uint32_t queueMem[osNumberOfMessages]; /*!< Points to the queue memory */
|
||||
uint32_t time_start; /*!< The time to start timeout */
|
||||
uint32_t timeout; /*!< Timeout to wait in milliseconds */
|
||||
task_handler_t waitingTask; /*!< Handler to the waiting task */
|
||||
}msg_queue_t;
|
||||
|
||||
/*! @brief Type for a message queue handler */
|
||||
typedef msg_queue_t* msg_queue_handler_t;
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define OSA_WAIT_FOREVER 0xFFFFFFFFU
|
||||
|
||||
/*! @brief How many tasks can the bare metal support. */
|
||||
#define TASK_MAX_NUM 7
|
||||
|
||||
/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */
|
||||
#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR))
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
extern void DefaultISR(void);
|
||||
|
||||
/*!
|
||||
* @name Thread management
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Defines a task.
|
||||
*
|
||||
* This macro defines resources for a task statically. Then, the OSA_TaskCreate
|
||||
* creates the task based-on these resources.
|
||||
*
|
||||
* @param task The task function.
|
||||
* @param stackSize The stack size this task needs in bytes.
|
||||
*/
|
||||
|
||||
#define PRIORITY_OSA_TO_RTOS(osa_prio) (osa_prio)
|
||||
#define PRIORITY_RTOS_TO_OSA(rtos_prio) (rtos_prio)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*!
|
||||
* @brief Calls all task functions one time except for the current task.
|
||||
*
|
||||
* This function calls all other task functions one time. If current
|
||||
* task is waiting for an event triggered by other tasks, this function
|
||||
* could be used to trigger the event.
|
||||
*
|
||||
* @note There should be only one task calls this function, if more than
|
||||
* one task call this function, stack overflow may occurs. Be careful
|
||||
* to use this function.
|
||||
*
|
||||
*/
|
||||
void OSA_PollAllOtherTasks(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus*/
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif /* __FSL_OS_ABSTRACTION_BM_H__ */
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
||||
Vendored
Executable
+53
@@ -0,0 +1,53 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
|
||||
#ifndef _FSL_OS_ABSTRACTION_CONFIG_H_
|
||||
#define _FSL_OS_ABSTRACTION_CONFIG_H_
|
||||
|
||||
#ifndef osNumberOfSemaphores
|
||||
#define osNumberOfSemaphores 5
|
||||
#endif
|
||||
#ifndef osNumberOfMutexes
|
||||
#define osNumberOfMutexes 5
|
||||
#endif
|
||||
#ifndef osNumberOfMessageQs
|
||||
#define osNumberOfMessageQs 0
|
||||
#endif
|
||||
#ifndef osNumberOfMessages
|
||||
#define osNumberOfMessages 10
|
||||
#endif
|
||||
#ifndef osNumberOfEvents
|
||||
#define osNumberOfEvents 5
|
||||
#endif
|
||||
|
||||
#ifndef CPU_JN518X
|
||||
#ifndef gMainThreadStackSize_c
|
||||
#define gMainThreadStackSize_c 1024
|
||||
#endif
|
||||
#else
|
||||
#if !defined gMainThreadStackSize_c || (gMainThreadStackSize_c < 1200)
|
||||
#undef gMainThreadStackSize_c
|
||||
#define gMainThreadStackSize_c 1200
|
||||
#endif
|
||||
#endif
|
||||
#ifndef gMainThreadPriority_c
|
||||
#define gMainThreadPriority_c 7
|
||||
#endif
|
||||
|
||||
#ifndef gTaskMultipleInstancesManagement_c
|
||||
#define gTaskMultipleInstancesManagement_c 0
|
||||
#endif
|
||||
|
||||
#ifndef osCustomStartup
|
||||
#define osCustomStartup 0
|
||||
#endif
|
||||
|
||||
#endif /* _FSL_OS_ABSTRACTION_CONFIG_H_ */
|
||||
Vendored
Executable
+161
@@ -0,0 +1,161 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2013-2014, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
#if !defined(__FSL_OS_ABSTRACTION_FREERTOS_H__)
|
||||
#define __FSL_OS_ABSTRACTION_FREERTOS_H__
|
||||
|
||||
#if defined ( __IAR_SYSTEMS_ICC__ )
|
||||
/**
|
||||
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
|
||||
* http://supp.iar.com/Support/?note=24725
|
||||
*/
|
||||
#define MISRAC_DISABLE _Pragma ("diag_suppress= \
|
||||
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
|
||||
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
|
||||
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
|
||||
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
|
||||
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
|
||||
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
|
||||
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
|
||||
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
|
||||
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
|
||||
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
|
||||
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
|
||||
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
|
||||
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
|
||||
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
|
||||
Pm155")
|
||||
|
||||
#define MISRAC_ENABLE _Pragma ("diag_default= \
|
||||
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
|
||||
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
|
||||
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
|
||||
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
|
||||
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
|
||||
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
|
||||
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
|
||||
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
|
||||
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
|
||||
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
|
||||
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
|
||||
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
|
||||
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
|
||||
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
|
||||
Pm155")
|
||||
#else
|
||||
/* Empty MISRA C macros for other toolchains. */
|
||||
#define MISRAC_DISABLE
|
||||
#define MISRAC_ENABLE
|
||||
#endif
|
||||
|
||||
MISRAC_DISABLE
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "event_groups.h"
|
||||
MISRAC_ENABLE
|
||||
|
||||
/*!
|
||||
* @addtogroup os_abstraction_free_rtos
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */
|
||||
typedef TaskHandle_t task_handler_t;
|
||||
|
||||
/*! @brief Type for a task stack.*/
|
||||
typedef portSTACK_TYPE task_stack_t;
|
||||
|
||||
/*! @brief Type for task parameter */
|
||||
typedef void* task_param_t;
|
||||
|
||||
/*! @brief Type for a task function. */
|
||||
typedef pdTASK_CODE task_t;
|
||||
|
||||
/*! @brief Type for a mutex. */
|
||||
typedef xSemaphoreHandle mutex_t;
|
||||
|
||||
/*! @brief Type for a semaphore. */
|
||||
typedef xSemaphoreHandle semaphore_t;
|
||||
|
||||
/*! @brief Type for an event flags object.*/
|
||||
typedef EventBits_t event_flags_t;
|
||||
|
||||
/*! @brief Type for an event group object in FreeRTOS OS */
|
||||
typedef struct EventFreertos {
|
||||
bool_t autoClear; /*!< Auto clear or manual clear */
|
||||
EventGroupHandle_t eventHandler; /*!< FreeRTOS OS event handler */
|
||||
} event_freertos;
|
||||
|
||||
/*! @brief Type for an event group object */
|
||||
typedef event_freertos event_t;
|
||||
|
||||
/*! @brief Type for a message queue declaration and creation. */
|
||||
typedef xQueueHandle msg_queue_t;
|
||||
|
||||
/*! @brief Type for a message queue handler */
|
||||
typedef xQueueHandle msg_queue_handler_t;
|
||||
|
||||
|
||||
/*! @brief Constant to pass as timeout value in order to wait indefinitely. */
|
||||
#define OSA_WAIT_FOREVER 0xFFFFFFFFU
|
||||
|
||||
/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */
|
||||
#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU
|
||||
|
||||
/*! @brief The default interrupt handler installed in vector table. */
|
||||
#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR))
|
||||
|
||||
/*! @brief The Max depth of Enter/Exist Critical could be nested in interrupt. */
|
||||
#define OSA_MAX_ISR_CRITICAL_SECTION_DEPTH 0x8U
|
||||
|
||||
extern void DefaultISR(void);
|
||||
|
||||
/*!
|
||||
* @name Thread management
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
* @brief To provide unified task piority for upper layer, OSA layer makes conversion.
|
||||
*/
|
||||
#define PRIORITY_OSA_TO_RTOS(osa_prio) (configMAX_PRIORITIES - (osa_prio) -2)
|
||||
#define PRIORITY_RTOS_TO_OSA(rtos_prio) (configMAX_PRIORITIES - (rtos_prio) -2)
|
||||
|
||||
/* @}*/
|
||||
|
||||
|
||||
/*!
|
||||
* @name Message queues
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief This macro statically reserves the memory required for the queue.
|
||||
*
|
||||
* @param name Identifier for the memory region.
|
||||
* @param number Number of elements in the queue.
|
||||
* @param size Size of every elements in words.
|
||||
*/
|
||||
#define MSG_QUEUE_DECLARE(name, number, size) \
|
||||
msg_queue_t *name = NULL
|
||||
|
||||
/* @}*/
|
||||
|
||||
/*! @}*/
|
||||
|
||||
#endif // __FSL_OS_ABSTRACTION_FREERTOS_H__
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
||||
Vendored
Executable
+1527
File diff suppressed because it is too large
Load Diff
Vendored
Executable
+1173
File diff suppressed because it is too large
Load Diff
+485
@@ -0,0 +1,485 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE: Persistent Data Manager
|
||||
*
|
||||
* DESCRIPTION: Provide management of data which needs to persist over
|
||||
* cold or warm start
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5148, JN5142, JN5139].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2012. All rights reserved
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PDM_H_INCLUDED
|
||||
#define PDM_H_INCLUDED
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Include Files ***/
|
||||
/****************************************************************************/
|
||||
|
||||
#define PUBLIC
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @addtogroup PDM library
|
||||
* @{
|
||||
*/
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
#define PDM_EXTERNAL_FLASH
|
||||
#endif
|
||||
#define PDM_NUM_BLOCKS 128
|
||||
#ifdef PDM_EXTERNAL_FLASH
|
||||
#define PDM_NAME_SIZE 16
|
||||
#else
|
||||
#define PDM_NAME_SIZE 7
|
||||
#ifndef PDM_USER_SUPPLIED_ID
|
||||
#define PDM_USER_SUPPLIED_ID /* Defaulting to having this enabled */
|
||||
#endif
|
||||
#endif
|
||||
#define PDM_INVALID_ID ((uint16)(-1))
|
||||
|
||||
/* PDM ID range allocation reservations
|
||||
* Each PDM_ID_BASE_xxx below is the base value for a block of 256 (0x100) IDs.
|
||||
* Within a module the individual IDs used by that module will be an offset from
|
||||
* this base.
|
||||
*
|
||||
* These ID ranges should not be re-used by other modules, even if the modules
|
||||
* are not both present in the build.
|
||||
*
|
||||
* Values should not be changed. Reserve a new range instead of changing an
|
||||
* existing range.
|
||||
*/
|
||||
#define PDM_ID_BASE_APP_ZB (0x0000) /* 0x0000?0x00ff: ZigBee Application Notes */
|
||||
#define PDM_ID_BASE_ZPSAPL (0xf000) /* 0xf000?0xf0ff: ZigBee ZPS APL layer */
|
||||
#define PDM_ID_BASE_ZPSNWK (0xf100) /* 0xf100?0xf1ff: ZigBee ZPS NWK layer */
|
||||
#define PDM_ID_BASE_RADIO (0xff00) /* 0xff00?0xffff: Radio driver */
|
||||
|
||||
/* PDM ID individual allocation reservations
|
||||
* Each PDM_ID_xxx below is an individual ID within one of the reserved ranges.
|
||||
* Individual IDs need to be declared here only if they are shared between modules.
|
||||
* Please include a descriptive comment to aid accurate identification.
|
||||
*/
|
||||
#define PDM_ID_RADIO_SETTINGS (PDM_ID_BASE_RADIO + 0x0000) /* Holds radio KMOD calibration data */
|
||||
|
||||
/* Defined because still using heap in PDM builds */
|
||||
#define PDM_USE_HEAP
|
||||
|
||||
#if (defined PDM_USE_HEAP)
|
||||
/* Empty declaration: buffer not needed */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments)
|
||||
#else
|
||||
/* Macro to create a static block of RAM to use instead of heap
|
||||
NOTE: Must be declared at module scope, not within a function
|
||||
NOTE: Value of 12 is based on size of tsPDM_FileSystemRecord */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments) \
|
||||
PUBLIC uint8 au8PDM_HeapBuffer[(u8NumberOfSegments) * 12] __attribute__((aligned (4)))
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_E_STATUS_OK,
|
||||
PDM_E_STATUS_INVLD_PARAM,
|
||||
// NVM based PDM codes
|
||||
PDM_E_STATUS_PDM_FULL,
|
||||
PDM_E_STATUS_NOT_SAVED,
|
||||
PDM_E_STATUS_RECOVERED,
|
||||
PDM_E_STATUS_PDM_RECOVERED_NOT_SAVED,
|
||||
PDM_E_STATUS_USER_BUFFER_SIZE,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_NO_INCREMENT,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_OK,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_COMPLETE,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_INCOMPLETE,
|
||||
PDM_E_STATUS_INTERNAL_ERROR
|
||||
} PDM_teStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_RECOVERY_STATE_NONE = 0,
|
||||
PDM_RECOVERY_STATE_NEW, // 1
|
||||
PDM_RECOVERY_STATE_RECOVERED, // 2
|
||||
PDM_RECOVERY_STATE_RECOVERED_NOT_READ, // 3
|
||||
PDM_RECOVERY_STATE_SAVED, // 4
|
||||
PDM_RECOVERY_STATE_NOT_SAVED, // 5
|
||||
PDM_RECOVERY_STATE_APPENDED, // 6
|
||||
// do not move
|
||||
PDM_RECOVERY_STATE_NUMBER
|
||||
} PDM_teRecoveryState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* this function gets called after a cold or warm start */
|
||||
void (*prInitHwCb)(void);
|
||||
|
||||
/* this function gets called to erase the given sector */
|
||||
void (*prEraseCb)(uint8_t u8Sector);
|
||||
|
||||
/* this function gets called to write data to an addresss
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prWriteCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
|
||||
/* this function gets called to read data from an address
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prReadCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
} PDM_tsHwFncTable;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_TRIGGER_VALUE_REACHED = 0,
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_MAXIMUM_REACHED,
|
||||
E_PDM_SYSTEM_EVENT_SAVE_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_NOT_ENOUGH_SPACE,
|
||||
E_PDM_SYSTEM_EVENT_LARGEST_RECORD_FULL_SAVE_NO_LONGER_POSSIBLE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_CHECKSUM_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_SAVE_OK,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_READ_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_WRITE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_ERASE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_CHECK_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_DATA_WRITE_FAIL,
|
||||
// nerdy event codes
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIRED,
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIR_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_INTERNAL_BUFFER_WEAR_COUNT_SWAP,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_DUPLICATE_FILE_SEGMENT_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_ERROR,
|
||||
// used in test harness
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_PREWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_POSTWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_DUPLICATE_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_VERIFY_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SMART_SAVE,
|
||||
E_PDM_SYSTEM_EVENT_FULL_SAVE
|
||||
} PDM_eSystemEventCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32eventNumber;
|
||||
PDM_eSystemEventCode eSystemEventCode;
|
||||
} PDM_tfpSystemEventCallback;
|
||||
|
||||
typedef void (*PDM_tpfvSystemEventCallback)(uint32_t u32eventNumber, PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Initialise the PDM
|
||||
*
|
||||
* This function is to be called in order to initialise the PDM module
|
||||
* call this EVERY cold start and EVERY warm start
|
||||
*
|
||||
* @param u16StartSegment: Start segment in flash
|
||||
* @param u8NumberOfSegments: number of contiguous segments from u16StartSegment
|
||||
* that belong to the PDM NVM space.
|
||||
* @param fpvPDM_SystemEventCallback: function pointer passed by using layer
|
||||
* to be notified of events/errors
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success PDM_E_STATUS_INTERNAL_ERROR otherwise
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eInitialise(uint16_t u16StartSegment,
|
||||
uint8_t u8NumberOfSegments,
|
||||
PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record
|
||||
*
|
||||
* This function saves the specified application data from RAM to the specified record
|
||||
* in NVM. The record is identified by means of a 16-bit user-defined value.
|
||||
* When a data record is saved to the NVM for the first time, the data is written provided
|
||||
* there are enough NVM segments available to hold the data. Upon subsequent save
|
||||
* requests, if there has been a change between the RAM-based and NVM-based data
|
||||
* buffers then the PDM will attempt to re-save only the segments that have changed
|
||||
* (if no data has changed, no save will be performed). This is advantageous due to the
|
||||
* restricted size of the NVM and the constraint that old data must be preserved while
|
||||
* saving changed data to the NVM.
|
||||
* Provided that you have registered a callback function with the PDM (see Section 6.3),
|
||||
* the callback mechanism will signal when a save has failed. Upon failure, the callback
|
||||
* function will be invoked and pass the event E_PDM_SYSTEM_EVENT_DESCRIPTOR_SAVE_FAILED
|
||||
* to the application
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (specified record ID is invalid)
|
||||
* @retval PDM_E_STATUS_NOT_SAVED (save to NVM failed)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordData(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record next time in idle task
|
||||
*
|
||||
* Like PDM_eSaveRecordData, except that the record information is queued to
|
||||
* saved in the idle task, when PDM_vIdleTask is called. Note that if the
|
||||
* internal queue is full, the first record on the queue is saved immediately
|
||||
* to make space for this record.
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordDataInIdleTask(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save queued PDM records
|
||||
*
|
||||
* Synchronously saves any queued record writes that have been generated by
|
||||
* calls to PDM_eSaveRecordDataInIdleTask. To avoid this function taking too
|
||||
* much time, the number of records that can be written can be limited by
|
||||
* the u8WritesAllowed parameter. Use a value of 255 to effectively avoid
|
||||
* this limit.
|
||||
* @param u8WritesAllowed Maximum number of records that can be written
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vIdleTask(uint8_t u8WritesAllowed);
|
||||
|
||||
/*!
|
||||
* @brief Purge the pending event available in the queue
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vQueuePurge(void);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Reads Partial Data from an Existing Record in the File System
|
||||
*
|
||||
* This function appends data to a record previously written.
|
||||
* The record is identified by means of a 16-bit user-defined value.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read from
|
||||
* @param u16TableOffset Data Offset
|
||||
* @param pu8DataBuffer Data Buffer
|
||||
* @param u16DataLength Length of input data, in bytes.
|
||||
* @param pu16DataBytesRead Number Of Data Bytes Read u16IdValue
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (error in arguments)
|
||||
* @retval PDM_E_STATUS_INTERNAL_ERROR
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadPartialDataFromExistingRecord(uint16_t u16IdValue,
|
||||
uint16_t u16TableOffset,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function reads the specified record of application data from the NVM and stores
|
||||
* the read data in the supplied data buffer in RAM. The record is specified using its
|
||||
* unique 16-bit identifier.
|
||||
* Before calling this function, it may be useful to call PDM_bDoesDataExist() in order
|
||||
* to determine whether a record with the specified identifier exists in the EEPROM and,
|
||||
* if it does, to obtain its size.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read
|
||||
* @param pvDataBuffer Pointer to the data buffer in RAM where the read data is to
|
||||
* be stored
|
||||
* @param u16DataBufferLength Length of the data buffer, in bytes
|
||||
* @param pu16DataBytesRead Pointer to a location to receive the number of data bytes
|
||||
* read
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM otherwise i.e. specified record ID is invalid
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadDataFromRecord(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes the specified record of application data in NVM.
|
||||
* @see PDM_eDeleteAllData to alternatively delete all records in NVM
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be deleted
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteDataRecord(uint16_t u16IdValue);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes all records in NVM, including both application data and stack
|
||||
* context data, resulting in an empty PDM file system. The NVM segment Wear Count
|
||||
* values are preserved (and incremented) throughout this function call.
|
||||
* This function is to be used with extreme care in a Zigbee application context
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteAllDataRecords(void);
|
||||
|
||||
/*!
|
||||
* @brief Seeks for a certain record by record identifier
|
||||
*
|
||||
* This function checks whether data associated with thd specified record ID
|
||||
* exists in the NVM. If the data record exists, the function returns the data
|
||||
* length, in bytes, in a location to which a pointer must be provided.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be found
|
||||
* @param pu16DataLength Pointer to location to receive length, in bytes,
|
||||
* of data record (if any) associated with specified record ID
|
||||
*
|
||||
* @retval true if record was fond false otherwise
|
||||
*/
|
||||
PUBLIC bool_t PDM_bDoesDataExist(uint16_t u16IdValue, uint16_t *pu16DataLength);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are left in the PDM space
|
||||
*
|
||||
* This function returns the number of unused segments that remain in the NVM.
|
||||
* Note that the returned parameter being a uint8_t the total expected number of
|
||||
* segments cannot exceed 255
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of PDM NVM segments free
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentCapacity(void);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are occupied in the PDM space
|
||||
*
|
||||
* This function returns the number of used segments in the NVM
|
||||
* @see PDM_u8GetSegmentCapacity
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of NVM segments used
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentOccupancy(void);
|
||||
|
||||
/*!
|
||||
* @brief Register a User defined system callback function
|
||||
*
|
||||
* This function registers a callback function that will be called in error events
|
||||
* @see PDM_pfGetSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param fpvPDM_SystemEventCallback function to replace the one that was set on PDM initialisation
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vRegisterSystemCallback(PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the previously defined system callback function
|
||||
*
|
||||
* This function retrieves the callback function that has been set by PDM_eInitialise
|
||||
* or PDM_vRegisterSystemCallback
|
||||
* @see PDM_vRegisterSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval fpvPDM_SystemEventCallback function used to notify error events
|
||||
*/
|
||||
PUBLIC PDM_tpfvSystemEventCallback PDM_pfGetSystemCallback(void);
|
||||
|
||||
PUBLIC void PDM_vSetWearCountTriggerLevel(uint32_t u32WearCountTriggerLevel);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetSegmentWearCount(uint8_t u8SegmentIndex, uint32_t *pu32WearCount);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetDeviceWearCountProfile(uint32_t au32WearCount[], uint8_t u8NumberOfSegments);
|
||||
|
||||
PUBLIC void PDM_vSetWearLevelDifference(uint32_t u32WearLevelDifference);
|
||||
|
||||
int PDM_Init(void);
|
||||
|
||||
#if defined UART_DEBUG
|
||||
PUBLIC void vPDM_InitialiseDisplayDataInFileSystem(uint16_t *pau16PDMFileIDrecord, uint8_t u8NumberOfPDMSegments);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInFileSystem(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayDataWithIdInFileSystem(uint16_t u16IdValue);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInNVM(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayNVMsegmentData(uint8_t u8SegmentIndex);
|
||||
|
||||
PUBLIC char *psPDM_PrintEventID(PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
PUBLIC int iPDM_ReadRawNVMsegmentDataToBuffer(uint8_t u8SegmentIndex,
|
||||
uint8_t *pu8SegmentDataBuffer,
|
||||
uint16_t *pu16SegmentDataSize);
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
extern PUBLIC const uint32_t PDM_g_u32Version;
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /*PDM_H_INCLUDED*/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** END OF FILE ***/
|
||||
/****************************************************************************/
|
||||
BIN
Binary file not shown.
+488
@@ -0,0 +1,488 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE: Persistent Data Manager
|
||||
*
|
||||
* DESCRIPTION: Provide management of data which needs to persist over
|
||||
* cold or warm start
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5148, JN5142, JN5139].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2012. All rights reserved
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PDM_H_INCLUDED
|
||||
#define PDM_H_INCLUDED
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Include Files ***/
|
||||
/****************************************************************************/
|
||||
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
#define PUBLIC
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @addtogroup PDM library
|
||||
* @{
|
||||
*/
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
#define PDM_EXTERNAL_FLASH
|
||||
#endif
|
||||
#define PDM_NUM_BLOCKS 128
|
||||
#ifdef PDM_EXTERNAL_FLASH
|
||||
#define PDM_NAME_SIZE 16
|
||||
#else
|
||||
#define PDM_NAME_SIZE 7
|
||||
#ifndef PDM_USER_SUPPLIED_ID
|
||||
#define PDM_USER_SUPPLIED_ID /* Defaulting to having this enabled */
|
||||
#endif
|
||||
#endif
|
||||
#define PDM_INVALID_ID ((uint16)(-1))
|
||||
|
||||
/* PDM ID range allocation reservations
|
||||
* Each PDM_ID_BASE_xxx below is the base value for a block of 256 (0x100) IDs.
|
||||
* Within a module the individual IDs used by that module will be an offset from
|
||||
* this base.
|
||||
*
|
||||
* These ID ranges should not be re-used by other modules, even if the modules
|
||||
* are not both present in the build.
|
||||
*
|
||||
* Values should not be changed. Reserve a new range instead of changing an
|
||||
* existing range.
|
||||
*/
|
||||
#define PDM_ID_BASE_APP_ZB (0x0000) /* 0x0000?0x00ff: ZigBee Application Notes */
|
||||
#define PDM_ID_BASE_ZPSAPL (0xf000) /* 0xf000?0xf0ff: ZigBee ZPS APL layer */
|
||||
#define PDM_ID_BASE_ZPSNWK (0xf100) /* 0xf100?0xf1ff: ZigBee ZPS NWK layer */
|
||||
#define PDM_ID_BASE_RADIO (0xff00) /* 0xff00?0xffff: Radio driver */
|
||||
|
||||
/* PDM ID individual allocation reservations
|
||||
* Each PDM_ID_xxx below is an individual ID within one of the reserved ranges.
|
||||
* Individual IDs need to be declared here only if they are shared between modules.
|
||||
* Please include a descriptive comment to aid accurate identification.
|
||||
*/
|
||||
#define PDM_ID_RADIO_SETTINGS (PDM_ID_BASE_RADIO + 0x0000) /* Holds radio KMOD calibration data */
|
||||
|
||||
/* Defined because still using heap in PDM builds */
|
||||
#define PDM_USE_HEAP
|
||||
|
||||
#if (defined PDM_USE_HEAP)
|
||||
/* Empty declaration: buffer not needed */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments)
|
||||
#else
|
||||
/* Macro to create a static block of RAM to use instead of heap
|
||||
NOTE: Must be declared at module scope, not within a function
|
||||
NOTE: Value of 12 is based on size of tsPDM_FileSystemRecord */
|
||||
#define PDM_DECLARE_BUFFER(u16StartSegment, u8NumberOfSegments) \
|
||||
PUBLIC uint8 au8PDM_HeapBuffer[(u8NumberOfSegments) * 12] __attribute__((aligned (4)))
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_E_STATUS_OK,
|
||||
PDM_E_STATUS_INVLD_PARAM,
|
||||
// NVM based PDM codes
|
||||
PDM_E_STATUS_PDM_FULL,
|
||||
PDM_E_STATUS_NOT_SAVED,
|
||||
PDM_E_STATUS_RECOVERED,
|
||||
PDM_E_STATUS_PDM_RECOVERED_NOT_SAVED,
|
||||
PDM_E_STATUS_USER_BUFFER_SIZE,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_NO_INCREMENT,
|
||||
PDM_E_STATUS_BITMAP_SATURATED_OK,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_COMPLETE,
|
||||
PDM_E_STATUS_IMAGE_BITMAP_INCOMPLETE,
|
||||
PDM_E_STATUS_INTERNAL_ERROR
|
||||
} PDM_teStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PDM_RECOVERY_STATE_NONE = 0,
|
||||
PDM_RECOVERY_STATE_NEW, // 1
|
||||
PDM_RECOVERY_STATE_RECOVERED, // 2
|
||||
PDM_RECOVERY_STATE_RECOVERED_NOT_READ, // 3
|
||||
PDM_RECOVERY_STATE_SAVED, // 4
|
||||
PDM_RECOVERY_STATE_NOT_SAVED, // 5
|
||||
PDM_RECOVERY_STATE_APPENDED, // 6
|
||||
// do not move
|
||||
PDM_RECOVERY_STATE_NUMBER
|
||||
} PDM_teRecoveryState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* this function gets called after a cold or warm start */
|
||||
void (*prInitHwCb)(void);
|
||||
|
||||
/* this function gets called to erase the given sector */
|
||||
void (*prEraseCb)(uint8_t u8Sector);
|
||||
|
||||
/* this function gets called to write data to an addresss
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prWriteCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
|
||||
/* this function gets called to read data from an address
|
||||
* within a given sector. address zero is the start of the
|
||||
* given sector */
|
||||
void (*prReadCb)(uint8_t u8Sector,
|
||||
#ifdef SE_HOST_COPROCESSOR
|
||||
uint32_t u32Addr,
|
||||
uint32_t u32Len,
|
||||
#else
|
||||
uint16_t u16Addr,
|
||||
uint16_t u16Len,
|
||||
#endif
|
||||
uint8_t *pu8Data);
|
||||
} PDM_tsHwFncTable;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_TRIGGER_VALUE_REACHED = 0,
|
||||
E_PDM_SYSTEM_EVENT_WEAR_COUNT_MAXIMUM_REACHED,
|
||||
E_PDM_SYSTEM_EVENT_SAVE_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_NOT_ENOUGH_SPACE,
|
||||
E_PDM_SYSTEM_EVENT_LARGEST_RECORD_FULL_SAVE_NO_LONGER_POSSIBLE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_CHECKSUM_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_SAVE_OK,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_READ_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_WRITE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_DATA_ERASE_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_CHECK_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_BLANK_DATA_WRITE_FAIL,
|
||||
// nerdy event codes
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIRED,
|
||||
E_PDM_SYSTEM_EVENT_NVM_SEGMENT_HEADER_REPAIR_FAILED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_INTERNAL_BUFFER_WEAR_COUNT_SWAP,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_DUPLICATE_FILE_SEGMENT_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SYSTEM_ERROR,
|
||||
// used in test harness
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_PREWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEGMENT_POSTWRITE,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_DUPLICATE_DETECTED,
|
||||
E_PDM_SYSTEM_EVENT_SEQUENCE_VERIFY_FAIL,
|
||||
E_PDM_SYSTEM_EVENT_SMART_SAVE,
|
||||
E_PDM_SYSTEM_EVENT_FULL_SAVE
|
||||
} PDM_eSystemEventCode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t u32eventNumber;
|
||||
PDM_eSystemEventCode eSystemEventCode;
|
||||
} PDM_tfpSystemEventCallback;
|
||||
|
||||
typedef void (*PDM_tpfvSystemEventCallback)(uint32_t u32eventNumber, PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/*!
|
||||
* @brief Initialise the PDM
|
||||
*
|
||||
* This function is to be called in order to initialise the PDM module
|
||||
* call this EVERY cold start and EVERY warm start
|
||||
*
|
||||
* @param u16StartSegment: Start segment in flash
|
||||
* @param u8NumberOfSegments: number of contiguous segments from u16StartSegment
|
||||
* that belong to the PDM NVM space.
|
||||
* @param fpvPDM_SystemEventCallback: function pointer passed by using layer
|
||||
* to be notified of events/errors
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success PDM_E_STATUS_INTERNAL_ERROR otherwise
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eInitialise(uint16_t u16StartSegment,
|
||||
uint8_t u8NumberOfSegments,
|
||||
PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record
|
||||
*
|
||||
* This function saves the specified application data from RAM to the specified record
|
||||
* in NVM. The record is identified by means of a 16-bit user-defined value.
|
||||
* When a data record is saved to the NVM for the first time, the data is written provided
|
||||
* there are enough NVM segments available to hold the data. Upon subsequent save
|
||||
* requests, if there has been a change between the RAM-based and NVM-based data
|
||||
* buffers then the PDM will attempt to re-save only the segments that have changed
|
||||
* (if no data has changed, no save will be performed). This is advantageous due to the
|
||||
* restricted size of the NVM and the constraint that old data must be preserved while
|
||||
* saving changed data to the NVM.
|
||||
* Provided that you have registered a callback function with the PDM (see Section 6.3),
|
||||
* the callback mechanism will signal when a save has failed. Upon failure, the callback
|
||||
* function will be invoked and pass the event E_PDM_SYSTEM_EVENT_DESCRIPTOR_SAVE_FAILED
|
||||
* to the application
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (specified record ID is invalid)
|
||||
* @retval PDM_E_STATUS_NOT_SAVED (save to NVM failed)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordData(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save a PDM record next time in idle task
|
||||
*
|
||||
* Like PDM_eSaveRecordData, except that the record information is queued to
|
||||
* saved in the idle task, when PDM_vIdleTask is called. Note that if the
|
||||
* internal queue is full, the first record on the queue is saved immediately
|
||||
* to make space for this record.
|
||||
* @param u16IdValue User-defined ID of the record to be saved
|
||||
* @param pvDataBuffer Pointer to data buffer to be saved in the record in NVM
|
||||
* @param u16Datalength Length of data to be saved, in bytes
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eSaveRecordDataInIdleTask(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16Datalength);
|
||||
|
||||
/*!
|
||||
* @brief Save queued PDM records
|
||||
*
|
||||
* Synchronously saves any queued record writes that have been generated by
|
||||
* calls to PDM_eSaveRecordDataInIdleTask. To avoid this function taking too
|
||||
* much time, the number of records that can be written can be limited by
|
||||
* the u8WritesAllowed parameter. Use a value of 255 to effectively avoid
|
||||
* this limit.
|
||||
* @param u8WritesAllowed Maximum number of records that can be written
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vIdleTask(uint8_t u8WritesAllowed);
|
||||
|
||||
/*!
|
||||
* @brief Purge the pending event available in the queue
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vQueuePurge(void);
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Reads Partial Data from an Existing Record in the File System
|
||||
*
|
||||
* This function appends data to a record previously written.
|
||||
* The record is identified by means of a 16-bit user-defined value.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read from
|
||||
* @param u16TableOffset Data Offset
|
||||
* @param pu8DataBuffer Data Buffer
|
||||
* @param u16DataLength Length of input data, in bytes.
|
||||
* @param pu16DataBytesRead Number Of Data Bytes Read u16IdValue
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK (success)
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM (error in arguments)
|
||||
* @retval PDM_E_STATUS_INTERNAL_ERROR
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadPartialDataFromExistingRecord(uint16_t u16IdValue,
|
||||
uint16_t u16TableOffset,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function reads the specified record of application data from the NVM and stores
|
||||
* the read data in the supplied data buffer in RAM. The record is specified using its
|
||||
* unique 16-bit identifier.
|
||||
* Before calling this function, it may be useful to call PDM_bDoesDataExist() in order
|
||||
* to determine whether a record with the specified identifier exists in the EEPROM and,
|
||||
* if it does, to obtain its size.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be read
|
||||
* @param pvDataBuffer Pointer to the data buffer in RAM where the read data is to
|
||||
* be stored
|
||||
* @param u16DataBufferLength Length of the data buffer, in bytes
|
||||
* @param pu16DataBytesRead Pointer to a location to receive the number of data bytes
|
||||
* read
|
||||
*
|
||||
* @retval PDM_E_STATUS_OK if success
|
||||
* @retval PDM_E_STATUS_INVLD_PARAM otherwise i.e. specified record ID is invalid
|
||||
*/
|
||||
PUBLIC PDM_teStatus PDM_eReadDataFromRecord(uint16_t u16IdValue,
|
||||
void *pvDataBuffer,
|
||||
uint16_t u16DataBufferLength,
|
||||
uint16_t *pu16DataBytesRead);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes the specified record of application data in NVM.
|
||||
* @see PDM_eDeleteAllData to alternatively delete all records in NVM
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be deleted
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteDataRecord(uint16_t u16IdValue);
|
||||
|
||||
/*!
|
||||
* @brief Delete a PDM record
|
||||
*
|
||||
* This function deletes all records in NVM, including both application data and stack
|
||||
* context data, resulting in an empty PDM file system. The NVM segment Wear Count
|
||||
* values are preserved (and incremented) throughout this function call.
|
||||
* This function is to be used with extreme care in a Zigbee application context
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vDeleteAllDataRecords(void);
|
||||
|
||||
/*!
|
||||
* @brief Seeks for a certain record by record identifier
|
||||
*
|
||||
* This function checks whether data associated with thd specified record ID
|
||||
* exists in the NVM. If the data record exists, the function returns the data
|
||||
* length, in bytes, in a location to which a pointer must be provided.
|
||||
*
|
||||
* @param u16IdValue User-defined ID of the record to be found
|
||||
* @param pu16DataLength Pointer to location to receive length, in bytes,
|
||||
* of data record (if any) associated with specified record ID
|
||||
*
|
||||
* @retval true if record was fond false otherwise
|
||||
*/
|
||||
PUBLIC bool_t PDM_bDoesDataExist(uint16_t u16IdValue, uint16_t *pu16DataLength);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are left in the PDM space
|
||||
*
|
||||
* This function returns the number of unused segments that remain in the NVM.
|
||||
* Note that the returned parameter being a uint8_t the total expected number of
|
||||
* segments cannot exceed 255
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of PDM NVM segments free
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentCapacity(void);
|
||||
|
||||
/*!
|
||||
* @brief Tells how many free segments are occupied in the PDM space
|
||||
*
|
||||
* This function returns the number of used segments in the NVM
|
||||
* @see PDM_u8GetSegmentCapacity
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval Number of NVM segments used
|
||||
*/
|
||||
PUBLIC uint8_t PDM_u8GetSegmentOccupancy(void);
|
||||
|
||||
/*!
|
||||
* @brief Register a User defined system callback function
|
||||
*
|
||||
* This function registers a callback function that will be called in error events
|
||||
* @see PDM_pfGetSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param fpvPDM_SystemEventCallback function to replace the one that was set on PDM initialisation
|
||||
*
|
||||
* @retval none
|
||||
*/
|
||||
PUBLIC void PDM_vRegisterSystemCallback(PDM_tpfvSystemEventCallback fpvPDM_SystemEventCallback);
|
||||
|
||||
/*!
|
||||
* @brief Retrieve the previously defined system callback function
|
||||
*
|
||||
* This function retrieves the callback function that has been set by PDM_eInitialise
|
||||
* or PDM_vRegisterSystemCallback
|
||||
* @see PDM_vRegisterSystemCallback
|
||||
* @see PDM_eInitialise
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
* @retval fpvPDM_SystemEventCallback function used to notify error events
|
||||
*/
|
||||
PUBLIC PDM_tpfvSystemEventCallback PDM_pfGetSystemCallback(void);
|
||||
|
||||
PUBLIC void PDM_vSetWearCountTriggerLevel(uint32_t u32WearCountTriggerLevel);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetSegmentWearCount(uint8_t u8SegmentIndex, uint32_t *pu32WearCount);
|
||||
|
||||
PUBLIC PDM_teStatus PDM_eGetDeviceWearCountProfile(uint32_t au32WearCount[], uint8_t u8NumberOfSegments);
|
||||
|
||||
PUBLIC void PDM_vSetWearLevelDifference(uint32_t u32WearLevelDifference);
|
||||
|
||||
int PDM_Init(void);
|
||||
|
||||
#if defined UART_DEBUG
|
||||
PUBLIC void vPDM_InitialiseDisplayDataInFileSystem(uint16_t *pau16PDMFileIDrecord, uint8_t u8NumberOfPDMSegments);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInFileSystem(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayDataWithIdInFileSystem(uint16_t u16IdValue);
|
||||
|
||||
PUBLIC void vPDM_DisplayDataInNVM(void);
|
||||
|
||||
PUBLIC int iPDM_DisplayNVMsegmentData(uint8_t u8SegmentIndex);
|
||||
|
||||
PUBLIC char *psPDM_PrintEventID(PDM_eSystemEventCode eSystemEventCode);
|
||||
|
||||
PUBLIC int iPDM_ReadRawNVMsegmentDataToBuffer(uint8_t u8SegmentIndex,
|
||||
uint8_t *pu8SegmentDataBuffer,
|
||||
uint16_t *pu16SegmentDataSize);
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
extern PUBLIC const uint32_t PDM_g_u32Version;
|
||||
|
||||
/*@}*/
|
||||
|
||||
#if defined __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /*PDM_H_INCLUDED*/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** END OF FILE ***/
|
||||
/****************************************************************************/
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* MODULE:
|
||||
*
|
||||
* COMPONENT:
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* This software is owned by NXP B.V. and/or its supplier and is protected
|
||||
* under applicable copyright laws. All rights are reserved. We grant You,
|
||||
* and any third parties, a license to use this software solely and
|
||||
* exclusively on NXP products [NXP Microcontrollers such as JN5168, JN5179].
|
||||
* You, and any third parties must reproduce the copyright and warranty notice
|
||||
* and any other legend of ownership on each copy or partial copy of the
|
||||
* software.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright NXP B.V. 2016. All rights reserved
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "projdefs.h"
|
||||
#include "portable.h"
|
||||
#else
|
||||
#include "MemManager.h"
|
||||
#endif
|
||||
|
||||
#include "FunctionLib.h"
|
||||
#include "fsl_debug_console.h"
|
||||
#include "Flash_Adapter.h"
|
||||
#include "PDM.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t u8Level;
|
||||
} tsMicroIntStorage;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define __WEAK_FUNC __attribute__((weak))
|
||||
#elif defined(__ICCARM__)
|
||||
#define __WEAK_FUNC __weak
|
||||
#elif defined( __CC_ARM )
|
||||
#define __WEAK_FUNC __weak
|
||||
#endif
|
||||
|
||||
#if gUsePdm_d
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Macro Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
/* In this module pvHeap_Alloc, vHeap_Free, vHeap_ResetHeap,
|
||||
* vMicroIntEnableOnly, vMicroIntRestoreState
|
||||
* are default weak implementations that can be overridden
|
||||
* for USE_RTOS or DUAL_MODE_APP builds */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Local Function Prototypes ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Local Variables ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Imported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Exported Functions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/*** Type Definitions ***/
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_HEAP_ALLOC = 0,
|
||||
E_HEAP_RESET,
|
||||
E_FUNCTION_MAX
|
||||
} eFunctionId;
|
||||
|
||||
|
||||
|
||||
/* Nested interrupt control */
|
||||
#ifndef MICRO_SET_PRIMASK_LEVEL
|
||||
#define MICRO_SET_PRIMASK_LEVEL(A) __set_PRIMASK(A)
|
||||
#endif
|
||||
// read back PRIMASK status into u32Store variable then disable the interrupts
|
||||
#ifndef MICRO_DISABLE_AND_SAVE_INTERRUPTS
|
||||
#define MICRO_DISABLE_AND_SAVE_INTERRUPTS(u32Store) \
|
||||
u32Store = __get_PRIMASK(); __disable_irq();
|
||||
#endif
|
||||
#ifndef MICRO_GET_ACTIVE_INT_LEVEL
|
||||
#define MICRO_GET_ACTIVE_INT_LEVEL __get_BASEPRI
|
||||
#endif
|
||||
#ifndef MICRO_SET_ACTIVE_INT_LEVEL_MAX
|
||||
#define MICRO_SET_ACTIVE_INT_LEVEL_MAX(A) __set_BASEPRI_MAX(A)
|
||||
#endif
|
||||
#ifndef MICRO_SET_ACTIVE_INT_LEVEL
|
||||
#define MICRO_SET_ACTIVE_INT_LEVEL(A) __set_BASEPRI(A)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: pvHeap_Alloc
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Allocates a block of memory from the heap.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to block, or NULL if the heap didn't have enough space. If block
|
||||
* was already assigned, returns original value and doesn't take anything
|
||||
* from heap.
|
||||
*
|
||||
* NOTES:
|
||||
* If buffer has already been allocated, it is not cleared.
|
||||
* If it is a fresh allocation, it is cleared on request.
|
||||
*
|
||||
****************************************************************************/
|
||||
__WEAK_FUNC void *pvHeap_Alloc(void *pvPointer, uint32_t u32BytesNeeded, bool_t bClear)
|
||||
{
|
||||
do {
|
||||
if (pvPointer != NULL) break;
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
pvPointer = pvPortMalloc(u32BytesNeeded);
|
||||
#else
|
||||
pvPointer = MEM_BufferAllocWithId(u32BytesNeeded, gPdmMemPoolId_c, (void*)__get_LR());
|
||||
#endif
|
||||
if (pvPointer == NULL) break;
|
||||
if (bClear)
|
||||
{
|
||||
FLib_MemSet(pvPointer, 0, u32BytesNeeded);
|
||||
}
|
||||
} while (0);
|
||||
return pvPointer;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: vHeap_Free
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Release a block of memory from the heap.
|
||||
*
|
||||
* RETURNS:
|
||||
* none
|
||||
* NOTES:
|
||||
*
|
||||
****************************************************************************/
|
||||
__WEAK_FUNC void vHeap_Free(void *pvPointer)
|
||||
{
|
||||
#if defined FSL_RTOS_FREE_RTOS && (FSL_RTOS_FREE_RTOS != 0)
|
||||
vPortFree(pvPointer);
|
||||
#else
|
||||
memStatus_t status;
|
||||
status = MEM_BufferFree(pvPointer);
|
||||
if (status != MEM_SUCCESS_c)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRINTF("MemMngt error freeing %08lx code=%d\r\n", (uint32_t)pvPointer, status);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__WEAK_FUNC void vHeap_ResetHeap(void)
|
||||
{
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__WEAK_FUNC void vMicroIntEnableOnly(tsMicroIntStorage *int_storage, uint32_t u32EnableMask)
|
||||
{
|
||||
uint32_t primask_lvl;
|
||||
MICRO_DISABLE_AND_SAVE_INTERRUPTS(primask_lvl);
|
||||
int_storage->u8Level = (uint8_t)MICRO_GET_ACTIVE_INT_LEVEL();
|
||||
MICRO_SET_ACTIVE_INT_LEVEL_MAX( 96 );
|
||||
MICRO_SET_PRIMASK_LEVEL(primask_lvl);
|
||||
}
|
||||
|
||||
__WEAK_FUNC void vMicroIntRestoreState(tsMicroIntStorage * int_storage)
|
||||
{
|
||||
MICRO_SET_ACTIVE_INT_LEVEL(int_storage->u8Level);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME: PDM_Init
|
||||
*
|
||||
* DESCRIPTION:
|
||||
* Wrapper to call PDM Initialization with the right Flash configuration parameters
|
||||
*
|
||||
* Note: FLASH_Init must have been called beforehand in order to initialize gFlashConfig.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0: if no error, negative value otherwise
|
||||
* NOTES:
|
||||
*
|
||||
****************************************************************************/
|
||||
int PDM_Init(void)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
#if gUsePdm_d
|
||||
static bool pdm_init_done = false;
|
||||
|
||||
do {
|
||||
if (pdm_init_done)
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
NV_Init(); /* used to setup the gFlashConfig.PFlashTotalSize value */
|
||||
|
||||
PDM_teStatus st = PDM_E_STATUS_INTERNAL_ERROR;
|
||||
uint8_t *base = (uint8_t*)NV_STORAGE_END_ADDRESS;
|
||||
size_t len = (size_t)((uint32_t)NV_STORAGE_START_ADDRESS + 1 - (uint32_t)NV_STORAGE_END_ADDRESS);
|
||||
#ifdef DEBUG
|
||||
uint8_t * flash_top = (uint8_t*)(gFlashConfig.PFlashTotalSize + gFlashConfig.PFlashBlockBase);
|
||||
uint8_t * flash_base = (uint8_t*)gFlashConfig.PFlashBlockBase;
|
||||
assert(base >= flash_base);
|
||||
assert(base + len <= flash_top);
|
||||
assert(len > FLASH_PAGE_SIZE*2);
|
||||
#endif
|
||||
#if !defined gPdmNbSegments || (gPdmNbSegments < NV_STORAGE_MAX_SECTORS)
|
||||
#error "gPdmNbSegments should match NV_STORAGE_MAX_SECTORS"
|
||||
#endif
|
||||
uint32_t sect_sz_log = Flib_Log2(gFlashConfig.PFlashSectorSize);
|
||||
st = PDM_eInitialise(ADDR2SEG(base, sect_sz_log),
|
||||
SIZE2SEGNB(len, sect_sz_log), NULL);
|
||||
|
||||
if (st != PDM_E_STATUS_OK)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRINTF("PDM/NVM misconfiguration\r\n");
|
||||
#endif
|
||||
assert(st != PDM_E_STATUS_OK);
|
||||
status = -st;
|
||||
break;
|
||||
}
|
||||
pdm_init_done = true;
|
||||
status = 0;
|
||||
} while (0);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
Vendored
Executable
+68
@@ -0,0 +1,68 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the header file for the Panic module.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
#ifndef __PANIC_H__
|
||||
#define __PANIC_H__
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#include "EmbeddedTypes.h"
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public type definitions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
typedef uint32_t panicId_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
panicId_t id;
|
||||
uint32_t location;
|
||||
uint32_t extra1;
|
||||
uint32_t extra2;
|
||||
uint32_t linkRegister;
|
||||
uint32_t cpsr_contents; /* may not be used initially */
|
||||
uint8_t stack_dump[4]; /* initially just contain the contents of the LR */
|
||||
} panicData_t;
|
||||
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public macros
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#ifndef gUsePanic_c
|
||||
#define gUsePanic_c 0
|
||||
#endif
|
||||
|
||||
#define ID_PANIC(grp,value) ((panicId_t)(((panicId_t)(grp) << 16)+((panicId_t)(value))))
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
void panic
|
||||
(
|
||||
panicId_t id,
|
||||
uint32_t location,
|
||||
uint32_t extra1,
|
||||
uint32_t extra2
|
||||
);
|
||||
|
||||
#endif /* __PANIC_H__ */
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* This is the source file for the Panic module.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
#include "Panic.h"
|
||||
#include "fsl_os_abstraction.h"
|
||||
#if gLoggingActive_d
|
||||
#include "dbg_logging.h"
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Private memory declarations
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
#if gUsePanic_c
|
||||
panicData_t panic_data;
|
||||
#endif
|
||||
|
||||
/*! *********************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
********************************************************************************** */
|
||||
|
||||
/*! *********************************************************************************
|
||||
* \brief This function will halt the system
|
||||
*
|
||||
* \param[in] id Description of the param2 in parameter
|
||||
* \param[in] location address where the Panic occurred
|
||||
* \param[in] extra1 parameter to be stored in Panic structure
|
||||
* \param[in] extra2 parameter to be stored in Panic structure
|
||||
*
|
||||
********************************************************************************** */
|
||||
|
||||
void panic( panicId_t id, uint32_t location, uint32_t extra1, uint32_t extra2 )
|
||||
{
|
||||
#if gUsePanic_c
|
||||
/* Save the Link Register */
|
||||
volatile uint32_t savedLR = 0;
|
||||
__asm("push {r2} ");
|
||||
__asm("push {LR} ");
|
||||
__asm("pop {r2} ");
|
||||
#if defined(__GNUC__)
|
||||
__asm("str r2, [SP, #24]");
|
||||
#else
|
||||
__asm("str r2, [SP, #4]");
|
||||
#endif
|
||||
__asm("pop {r2}");
|
||||
|
||||
panic_data.id = id;
|
||||
panic_data.location = location;
|
||||
panic_data.extra1 = extra1;
|
||||
panic_data.extra2 = extra2;
|
||||
panic_data.linkRegister = savedLR;
|
||||
panic_data.cpsr_contents = 0;
|
||||
|
||||
OSA_InterruptDisable(); /* disable interrupts */
|
||||
#if gLoggingActive_d
|
||||
DbgLogDump(1);
|
||||
#endif
|
||||
/* infinite loop just to ensure this routine never returns */
|
||||
for(;;)
|
||||
{
|
||||
__asm("NOP");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
void __attribute__((weak)) __assertion_failed(char* s) {}
|
||||
#endif
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*! *********************************************************************************
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* MCU reset related functions implementation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
********************************************************************************** */
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Include
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
#include "fsl_device_registers.h"
|
||||
|
||||
#ifdef CPU_JN518X
|
||||
#include "fsl_reset.h"
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Private type definitions
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Public prototypes
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
void ResetMCU(void);
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
*************************************************************************************
|
||||
* Public functions
|
||||
*************************************************************************************
|
||||
************************************************************************************/
|
||||
void ResetMCU(void)
|
||||
{
|
||||
#ifdef CPU_JN518X
|
||||
RESET_SystemReset();
|
||||
#else
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
while(1){}
|
||||
}
|
||||
|
||||
/********************************** EOF ***************************************/
|
||||
Reference in New Issue
Block a user