diff --git a/examples/Makefile-jn5189 b/examples/Makefile-jn5189 index 6cc5b67fa..834db2280 100755 --- a/examples/Makefile-jn5189 +++ b/examples/Makefile-jn5189 @@ -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 diff --git a/examples/Makefile-k32w061 b/examples/Makefile-k32w061 index 3c39573c3..ee8a2f83a 100755 --- a/examples/Makefile-k32w061 +++ b/examples/Makefile-k32w061 @@ -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) diff --git a/examples/platforms/k32w/jn5189/Makefile.am b/examples/platforms/k32w/jn5189/Makefile.am index d076268c3..b7ef9c89e 100755 --- a/examples/platforms/k32w/jn5189/Makefile.am +++ b/examples/platforms/k32w/jn5189/Makefile.am @@ -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 = \ diff --git a/examples/platforms/k32w/jn5189/Makefile.platform.am b/examples/platforms/k32w/jn5189/Makefile.platform.am index 0e279c904..494fbd6d7 100755 --- a/examples/platforms/k32w/jn5189/Makefile.platform.am +++ b/examples/platforms/k32w/jn5189/Makefile.platform.am @@ -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 += \ diff --git a/examples/platforms/k32w/jn5189/jn5189-sdk-config.h b/examples/platforms/k32w/jn5189/jn5189-sdk-config.h new file mode 100644 index 000000000..32280e961 --- /dev/null +++ b/examples/platforms/k32w/jn5189/jn5189-sdk-config.h @@ -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 diff --git a/examples/platforms/k32w/jn5189/jn5189.ld b/examples/platforms/k32w/jn5189/jn5189.ld index 44608e89e..1d0099f09 100755 --- a/examples/platforms/k32w/jn5189/jn5189.ld +++ b/examples/platforms/k32w/jn5189/jn5189.ld @@ -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") -} \ No newline at end of file +} diff --git a/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h b/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h index b9df9802b..51f7d27e6 100755 --- a/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h +++ b/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h @@ -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 diff --git a/examples/platforms/k32w/k32w061/Makefile.am b/examples/platforms/k32w/k32w061/Makefile.am index 123ddd111..fd88e64e5 100755 --- a/examples/platforms/k32w/k32w061/Makefile.am +++ b/examples/platforms/k32w/k32w061/Makefile.am @@ -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 = \ diff --git a/examples/platforms/k32w/k32w061/Makefile.platform.am b/examples/platforms/k32w/k32w061/Makefile.platform.am index b79dbd172..c36658872 100755 --- a/examples/platforms/k32w/k32w061/Makefile.platform.am +++ b/examples/platforms/k32w/k32w061/Makefile.platform.am @@ -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 += \ diff --git a/examples/platforms/k32w/k32w061/k32w061-sdk-config.h b/examples/platforms/k32w/k32w061/k32w061-sdk-config.h new file mode 100644 index 000000000..753860e82 --- /dev/null +++ b/examples/platforms/k32w/k32w061/k32w061-sdk-config.h @@ -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 diff --git a/examples/platforms/k32w/k32w061/k32w061.ld b/examples/platforms/k32w/k32w061/k32w061.ld index fbebd6423..ebaa60daf 100755 --- a/examples/platforms/k32w/k32w061/k32w061.ld +++ b/examples/platforms/k32w/k32w061/k32w061.ld @@ -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)); diff --git a/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h b/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h index bd2efaba5..c6e877b46 100755 --- a/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h +++ b/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h @@ -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 diff --git a/examples/platforms/k32w/src/settings_k32w.c b/examples/platforms/k32w/src/settings_k32w.c old mode 100755 new mode 100644 index f92dff9d1..cbbd62fe3 --- a/examples/platforms/k32w/src/settings_k32w.c +++ b/examples/platforms/k32w/src/settings_k32w.c @@ -37,353 +37,67 @@ #include #include #include -#include #include #include #include +#include #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); } diff --git a/examples/platforms/k32w/src/system.c b/examples/platforms/k32w/src/system.c old mode 100755 new mode 100644 index fd7339c43..abf83de62 --- a/examples/platforms/k32w/src/system.c +++ b/examples/platforms/k32w/src/system.c @@ -39,7 +39,10 @@ #include #include -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++; +} diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c new file mode 100755 index 000000000..2f55db224 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c @@ -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 */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h new file mode 100755 index 000000000..9c89723ce --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h @@ -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__ */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c new file mode 100755 index 000000000..5e6b88ad6 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c @@ -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 +#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 diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h new file mode 100755 index 000000000..047b2fd77 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h @@ -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 + +/*! ********************************************************************************* +************************************************************************************* +* 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< (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_ */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.c new file mode 100755 index 000000000..21ea993b0 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.c @@ -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; ihead == 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 + diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.h new file mode 100755 index 000000000..a094ce9bd --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Lists/GenericList.h @@ -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_*/ \ No newline at end of file diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h new file mode 100755 index 000000000..f9e6fb5b8 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h @@ -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 + +#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_ */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Source/MemManager.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Source/MemManager.c new file mode 100755 index 000000000..903d473dc --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/MemManager/Source/MemManager.c @@ -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; iallocStatus == 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; ipoolSize; 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); +} diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h new file mode 100755 index 000000000..0f8b2c21a --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h @@ -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 diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h new file mode 100755 index 000000000..1578be2e4 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h @@ -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 + ******************************************************************************/ + diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h new file mode 100755 index 000000000..d74baaf99 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h @@ -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_ */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h new file mode 100755 index 000000000..c1ba29243 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h @@ -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 + ******************************************************************************/ + diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c new file mode 100755 index 000000000..bb5fc93e3 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c @@ -0,0 +1,1527 @@ +/*! ********************************************************************************* +* Copyright (c) 2015, Freescale Semiconductor, Inc. +* Copyright 2016-2017 NXP +* All rights reserved. +* +* \file +* +* This is the source file for the OS Abstraction layer for MQXLite. +* +* SPDX-License-Identifier: BSD-3-Clause +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ + +#include "EmbeddedTypes.h" +#include "fsl_os_abstraction.h" +#include "fsl_os_abstraction_bm.h" +#include "fsl_common.h" +#include +#include "GenericList.h" + +/*! ********************************************************************************* +************************************************************************************* +* Private macros +************************************************************************************* +********************************************************************************** */ + +/* Weak function. */ +#if defined(__GNUC__) +#define __WEAK_FUNC __attribute__((weak)) +#elif defined(__ICCARM__) +#define __WEAK_FUNC __weak +#elif defined( __CC_ARM ) +#define __WEAK_FUNC __weak +#endif + +#ifdef DEBUG_ASSERT +#define OS_ASSERT(condition) if(!(condition))while(1); +#else +#define OS_ASSERT(condition) (void)(condition); +#endif + +#if (osNumberOfSemaphores || osNumberOfMutexes || osNumberOfEvents || osNumberOfMessageQs) +#define osObjectAlloc_c 1 +#else +#define osObjectAlloc_c 0 +#endif + +/************************************************************************************ +************************************************************************************* +* Private type definitions +************************************************************************************* +************************************************************************************/ + +typedef struct osMutexStruct_tag + { + uint32_t inUse; + mutex_t mutex; + }osMutexStruct_t; + +typedef struct osEventStruct_tag + { + uint32_t inUse; + event_t event; + }osEventStruct_t; + +typedef struct osSemaphoreStruct_tag + { + uint32_t inUse; + semaphore_t semaphore; + }osSemaphoreStruct_t; + +typedef struct osMsgQStruct_tag + { + uint32_t inUse; + msg_queue_t queue; + }osMsgQStruct_t; + +typedef struct osObjStruct_tag + { + uint32_t inUse; + uint32_t osObj; + }osObjStruct_t; + +typedef struct osObjectInfo_tag +{ + void* pHeap; + uint32_t objectStructSize; + uint32_t objNo; +}osObjectInfo_t; + + +/*! ********************************************************************************* +************************************************************************************* +* Private prototypes +************************************************************************************* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo); +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +#endif + +extern void main_task(void *argument); +void task_init(void); +__WEAK_FUNC void OSA_TimeInit(void); +__WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end); +osaStatus_t OSA_Init(void); +void OSA_Start(void); +static void OSA_InsertTaskBefore(task_handler_t newTCB, task_handler_t currentTCB); + +/*! ********************************************************************************* +************************************************************************************* +* Public memory declarations +************************************************************************************* +********************************************************************************** */ +#define main_taskStack NULL + +const uint8_t gUseRtos_c = USE_RTOS; /* USE_RTOS = 0 for BareMetal and 1 for OS */ + +/*! ********************************************************************************* +************************************************************************************* +* Private memory declarations +************************************************************************************* +********************************************************************************** */ + +list_t threadList; + +#if osNumberOfSemaphores +osSemaphoreStruct_t osSemaphoreHeap[osNumberOfSemaphores]; +const osObjectInfo_t osSemaphoreInfo = {osSemaphoreHeap, sizeof(osSemaphoreStruct_t),osNumberOfSemaphores}; +#endif + +#if osNumberOfMutexes +osMutexStruct_t osMutexHeap[osNumberOfMutexes]; +const osObjectInfo_t osMutexInfo = {osMutexHeap, sizeof(osMutexStruct_t),osNumberOfMutexes}; +#endif + +#if osNumberOfEvents +osEventStruct_t osEventHeap[osNumberOfEvents]; +const osObjectInfo_t osEventInfo = {osEventHeap, sizeof(osEventStruct_t),osNumberOfEvents}; +#endif + +#if osNumberOfMessageQs +osMsgQStruct_t osMsgQHeap[osNumberOfMessageQs]; +const osObjectInfo_t osMsgQInfo = {osMsgQHeap, sizeof(osMsgQStruct_t),osNumberOfMessageQs}; +#endif + +#if (TASK_MAX_NUM > 0) + +/* Global variales for task. */ +static task_handler_t g_curTask; /* Current task. */ +/* + * All task control blocks in g_taskControlBlockPool will be linked as a + * list, and the list is managed by the pointer g_freeTaskControlBlock. + */ +static task_control_block_t g_taskControlBlockPool[TASK_MAX_NUM]; + +/* + * Pointer to the free task control blocks. To create a task, we should get + * task control block from this pointer. When task is destroyed, the control + * block will be returned and managed by this pointer. + */ +static task_control_block_t *g_freeTaskControlBlock; + +/* Head node of task list, all tasks will be linked to this head node. */ +static task_control_block_t *p_taskListHead = NULL; +#endif +uint32_t gInterruptDisableCount = 0; +uint32_t gTickCounter = 0; + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EnableIRQGlobal + * Description : Disable system interrupt. + * + *END**************************************************************************/ +void OSA_EnableIRQGlobal(void) +{ + if (gInterruptDisableCount > 0) + { + gInterruptDisableCount--; + + if (gInterruptDisableCount == 0) + { + __enable_irq(); + } + /* call core API to enable the global interrupt*/ + } +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_DisableIRQGlobal + * Description : Disable system interrupt + * This function will disable the global interrupt by calling the core API + * + *END**************************************************************************/ +void OSA_DisableIRQGlobal(void) +{ + /* call core API to disable the global interrupt*/ + __disable_irq(); + + /* update counter*/ + gInterruptDisableCount++; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetId + * Description : This function is used to get current active task's handler. + * + *END**************************************************************************/ + +osaTaskId_t OSA_TaskGetId(void) +{ + return (osaTaskId_t)g_curTask; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EXT_TaskYield + * Description : When a task calls this function, it will give up CPU and put + * itself to the tail of ready list. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskYield(void) +{ + return osaStatus_Success; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetPriority + * Description : This function returns task's priority by task handler. + * + *END**************************************************************************/ + +osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId) +{ + task_handler_t handler = (task_handler_t)taskId; + return handler->priority; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskSetPriority + * Description : This function sets task's priority by task handler. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority) +{ + task_handler_t handler = (task_handler_t)taskId; + task_handler_t p; + + /* Remove task control block from task list. */ + handler->prev->next = handler->next; + handler->next->prev = handler->prev; + if( handler == p_taskListHead ) + { + p_taskListHead = handler->next; + } + + handler->priority = taskPriority; + /* Insert task control block into the task list. */ + if( handler->priority <= p_taskListHead->priority ) + { + /* New task has the highest priority */ + OSA_InsertTaskBefore(handler, p_taskListHead); + p_taskListHead = handler; + } + else if( handler->priority >= p_taskListHead->prev->priority ) + { + /* New task has the lowest priority */ + OSA_InsertTaskBefore(handler, p_taskListHead); + } + else + { + p = p_taskListHead->next; + + while (p != p_taskListHead) + { + if (handler->priority <= p->priority) + { + OSA_InsertTaskBefore(handler, p); + break; + } + p = p->next; + } + } + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : task_init + * Description : This function is used to initialize bare metal's task system, + * it will prepare task control block pool and initialize corresponding + * structures. This function should be called before creating any tasks. + * + *END**************************************************************************/ +void task_init(void) +{ + int32_t i = TASK_MAX_NUM-1; + + g_taskControlBlockPool[i].next = NULL; + + while (i--) + { + /* Link all task control blocks to a list. */ + g_taskControlBlockPool[i].next = &g_taskControlBlockPool[i+1]; + } + + g_freeTaskControlBlock = g_taskControlBlockPool; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskCreate + * Description : This function is used to create a task and make it ready. + * Param[in] : threadDef - Definition of the thread. + * task_param - Parameter to pass to the new thread. + * Return Thread handle of the new thread, or NULL if failed. + * + *END**************************************************************************/ +osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def,osaTaskParam_t task_param) +{ + osaTaskId_t taskId = NULL; + task_control_block_t *p_newTaskControlBlock; + task_control_block_t *p_currentTaskControlBlock; + + if (g_freeTaskControlBlock) + { + /* Get new task control block from pool. */ + p_newTaskControlBlock = g_freeTaskControlBlock; + g_freeTaskControlBlock = g_freeTaskControlBlock->next; + /* Set task entry and parameter.*/ + p_newTaskControlBlock->p_func = thread_def->pthread; + p_newTaskControlBlock->haveToRun = true; + p_newTaskControlBlock->priority = PRIORITY_OSA_TO_RTOS(thread_def->tpriority); + p_newTaskControlBlock->param = task_param; + p_newTaskControlBlock->next = NULL; + p_newTaskControlBlock->prev = NULL; + + if (p_taskListHead == NULL) + { + p_taskListHead = p_newTaskControlBlock; + p_taskListHead->next = p_taskListHead; + p_taskListHead->prev = p_taskListHead; + } + else if (p_newTaskControlBlock->priority <= p_taskListHead->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_taskListHead); + p_taskListHead = p_newTaskControlBlock; + } + else if (p_newTaskControlBlock->priority >= p_taskListHead->prev->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_taskListHead); + } + else + { + p_currentTaskControlBlock = p_taskListHead->next; + + while (p_currentTaskControlBlock != p_taskListHead) + { + if (p_newTaskControlBlock->priority <= p_currentTaskControlBlock->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_currentTaskControlBlock); + break; + } + p_currentTaskControlBlock = p_currentTaskControlBlock->next; + } + + } + /* Task handler is pointer of task control block. */ + taskId = (osaTaskId_t)p_newTaskControlBlock; + } + + return taskId; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskDestroy + * Description : This function destroy a task. + * Param[in] :taskId - Thread handle. + * Return osaStatus_Success if the task is destroied, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId) +{ + task_handler_t handler; + if(taskId == NULL) + { + return osaStatus_Error; + } + handler = (task_handler_t)taskId; + + /* Remove task control block from task list. */ + handler->prev->next = handler->next; + handler->next->prev = handler->prev; + + /* + * If current task is destroyed, then g_curTask will point to the previous + * task, so that the subsequent tasks could be called. Check the function + * OSA_Start for more details. + */ + if (handler == g_curTask) + { + g_curTask = handler->prev; + } + + /* Put task control block back to pool. */ + handler->prev = NULL; + handler->next = g_freeTaskControlBlock; + g_freeTaskControlBlock = handler; + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeInit + * Description : This function initializes the timer used in BM OSA, the + * functions such as OSA_TimeDelay, OSA_TimeGetMsec, and the timeout are all + * based on this timer. + * + *END**************************************************************************/ +__WEAK_FUNC void OSA_TimeInit(void) +{ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk); + SysTick->LOAD = SystemCoreClock/1000 - 1; + SysTick->VAL = 0; + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeDiff + * Description : This function gets the difference between two time stamp, + * time overflow is considered. + * + *END**************************************************************************/ +__WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end) +{ + if (time_end >= time_start) + { + return time_end - time_start; + } + else + { + return FSL_OSA_TIME_RANGE - time_start + time_end + 1; + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA__TimeDelay + * Description : This function is used to suspend the active thread for the given number of milliseconds. + * + *END**************************************************************************/ +void OSA_TimeDelay(uint32_t millisec) +{ + uint32_t currTime, timeStart; + + timeStart = OSA_TimeGetMsec(); + + do { + currTime = OSA_TimeGetMsec(); /* Get current time stamp */ + } while (millisec >= OSA_TimeDiff(timeStart, currTime)); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeGetMsec + * Description : This function gets current time in milliseconds. + * + *END**************************************************************************/ +__WEAK_FUNC uint32_t OSA_TimeGetMsec(void) +{ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + return gTickCounter; +#else + return 0; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeResetMsec + * Description : This function resets the current time to 0. + * + *END**************************************************************************/ +__WEAK_FUNC void OSA_TimeResetMsec(void) +{ + gTickCounter = 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreCreate + * Description : This function is used to create a semaphore. + * Return : Semaphore handle of the new semaphore, or NULL if failed. + * + *END**************************************************************************/ + +osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue) +{ +#if osNumberOfSemaphores + osaSemaphoreId_t semId; + osSemaphoreStruct_t* pSemStruct; + OSA_InterruptDisable(); + semId = pSemStruct = osObjectAlloc(&osSemaphoreInfo); + OSA_InterruptEnable(); + if(semId == NULL) + { + return NULL; + } + + pSemStruct->semaphore.semCount = initValue; + pSemStruct->semaphore.isWaiting = false; + pSemStruct->semaphore.time_start = 0u; + pSemStruct->semaphore.timeout = 0u; + + return semId; +#else + initValue=initValue; + return NULL; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreDestroy + * Description : This function is used to destroy a semaphore. + * Return : osaStatus_Success if the semaphore is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + OSA_InterruptDisable(); + osObjectFree(&osSemaphoreInfo, semId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + semId=semId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreWait + * Description : This function checks the semaphore's counting value, if it is + * positive, decreases it and returns osaStatus_Success, otherwise, timeout + * will be used for wait. The parameter timeout indicates how long should wait + * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will + * return osaStatus_Timeout immediately if semaphore is not positive. + * This function returns osaStatus_Success if the semaphore is received, returns + * osaStatus_Timeout if the semaphore is not received within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) +{ +#if osNumberOfSemaphores + osSemaphoreStruct_t* pSemStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + pSemStruct = (osSemaphoreStruct_t*)semId; + /* Check the sem count first. Deal with timeout only if not already set */ + + if (pSemStruct->semaphore.semCount) + { + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.semCount --; + pSemStruct->semaphore.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */ + return osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pSemStruct->semaphore.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pSemStruct->semaphore.timeout < OSA_TimeDiff(pSemStruct->semaphore.time_start, currentTime)) + { + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Timeout; + } + } + else if (millisec != osaWaitForever_c) /* If don't wait forever, start the timer */ + { + /* Start the timeout counter */ + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.isWaiting = true; + OSA_EnableIRQGlobal(); + pSemStruct->semaphore.time_start = OSA_TimeGetMsec(); + pSemStruct->semaphore.timeout = millisec; + } +#endif + } + + return osaStatus_Idle; +#else + semId=semId; + millisec=millisec; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphorePost + * Description : This function is used to wake up one task that wating on the + * semaphore. If no task is waiting, increase the semaphore. The function returns + * osaStatus_Success if the semaphre is post successfully, otherwise returns + * osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + osSemaphoreStruct_t* pSemStruct; + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + pSemStruct = (osSemaphoreStruct_t*)semId; + /* The max value is 0xFF */ + if (0xFF == pSemStruct->semaphore.semCount) + { + return osaStatus_Error; + } + OSA_DisableIRQGlobal(); + ++pSemStruct->semaphore.semCount; + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + semId=semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexCreate + * Description : This function is used to create a mutex. + * Return : Mutex handle of the new mutex, or NULL if failed. + * + *END**************************************************************************/ +osaMutexId_t OSA_MutexCreate(void) +{ +#if osNumberOfMutexes + osaMutexId_t mutexId; + osMutexStruct_t* pMutexStruct; + OSA_InterruptDisable(); + mutexId = pMutexStruct = osObjectAlloc(&osMutexInfo); + OSA_InterruptEnable(); + if(mutexId == NULL) + { + return NULL; + } + pMutexStruct->mutex.isLocked = false; + pMutexStruct->mutex.isWaiting = false; + pMutexStruct->mutex.time_start = 0u; + pMutexStruct->mutex.timeout = 0u; + return mutexId; +#else + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexLock + * Description : This function checks the mutex's status, if it is unlocked, + * lock it and returns osaStatus_Success, otherwise, wait for the mutex. + * MQX does not support timeout to wait for a mutex. + * This function returns osaStatus_Success if the mutex is obtained, returns + * osaStatus_Error if any errors occur during waiting. If the mutex has been + * locked, pass 0 as timeout will return osaStatus_Timeout immediately. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) +{ +#if osNumberOfMutexes + osMutexStruct_t* pMutexStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + pMutexStruct = (osMutexStruct_t*)mutexId; + + /* Always check first. Deal with timeout only if not available. */ + if (pMutexStruct->mutex.isLocked == false) + { + /* Get the lock and return success */ + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isLocked = true; + pMutexStruct->mutex.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and mutex is not available, return kStatus_OSA_Timeout. */ + return osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pMutexStruct->mutex.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pMutexStruct->mutex.timeout < OSA_TimeDiff(pMutexStruct->mutex.time_start, currentTime)) + { + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Timeout; + } + } + else if (millisec != osaWaitForever_c) /* If dont't wait forever, start timer. */ + { + /* Start the timeout counter */ + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isWaiting = true; + OSA_EnableIRQGlobal(); + pMutexStruct->mutex.time_start = OSA_TimeGetMsec(); + pMutexStruct->mutex.timeout = millisec; + } +#endif + } + + return osaStatus_Idle; +#else + mutexId=mutexId; + millisec=millisec; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexUnlock + * Description : This function is used to unlock a mutex. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + osMutexStruct_t* pMutexStruct; + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + pMutexStruct = (osMutexStruct_t*)mutexId; + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isLocked = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; +#else + mutexId=mutexId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexDestroy + * Description : This function is used to destroy a mutex. + * Return : osaStatus_Success if the lock object is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + OSA_InterruptDisable(); + osObjectFree(&osMutexInfo, mutexId); + OSA_InterruptEnable(); + + return osaStatus_Success; +#else + mutexId=mutexId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventCreate + * Description : This function is used to create a event object. + * Return : Event handle of the new event, or NULL if failed. + * + *END**************************************************************************/ +osaEventId_t OSA_EventCreate(bool_t autoClear) +{ +#if osNumberOfEvents + osaEventId_t eventId; + osEventStruct_t* pEventStruct; + OSA_InterruptDisable(); + eventId = pEventStruct = osObjectAlloc(&osEventInfo); + OSA_InterruptEnable(); + if(eventId == NULL) + { + return NULL; + } + pEventStruct->event.isWaiting = false; + pEventStruct->event.flags = 0; + pEventStruct->event.autoClear = autoClear; + pEventStruct->event.time_start = 0u; + pEventStruct->event.timeout = 0u; + pEventStruct->event.waitingTask = NULL; + return eventId; +#else + (void)autoClear; + return NULL; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventSet + * Description : Set one or more event flags of an event object. + * Return : osaStatus_Success if set successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + /* Set flags ensuring atomic operation */ + OSA_DisableIRQGlobal(); + pEventStruct->event.flags |= flagsToSet; + if (pEventStruct->event.waitingTask != NULL) + { + pEventStruct->event.waitingTask->haveToRun = true; + } + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToSet; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventClear + * Description : Clear one or more event flags of an event object. + * Return :osaStatus_Success if clear successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + /* Clear flags ensuring atomic operation */ + OSA_DisableIRQGlobal(); + pEventStruct->event.flags &= ~flagsToClear; + if (pEventStruct->event.flags != 0x00) + { + if (pEventStruct->event.waitingTask != NULL) + { + pEventStruct->event.waitingTask->haveToRun = true; + } + } + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToClear; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventWait + * Description : This function checks the event's status, if it meets the wait + * condition, return osaStatus_Success, otherwise, timeout will be used for + * wait. The parameter timeout indicates how long should wait in milliseconds. + * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value + * osaStatus_Timeout immediately if wait condition is not met. The event flags + * will be cleared if the event is auto clear mode. Flags that wakeup waiting + * task could be obtained from the parameter setFlags. + * This function returns osaStatus_Success if wait condition is met, returns + * osaStatus_Timeout if wait condition is not met within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + osaStatus_t retVal = osaStatus_Idle; + if(pSetFlags == NULL) + { + return osaStatus_Error; + } + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + + OSA_DisableIRQGlobal(); +#if (TASK_MAX_NUM > 0) + pEventStruct->event.waitingTask = OSA_TaskGetId(); +#endif + + *pSetFlags = pEventStruct->event.flags & flagsToWait; + + /* Check the event flag first, if does not meet wait condition, deal with timeout. */ + if ((((!waitAll) && (*pSetFlags))) || (*pSetFlags == flagsToWait)) + { + pEventStruct->event.isWaiting = false; + if(TRUE == pEventStruct->event.autoClear) + { + pEventStruct->event.flags &= ~flagsToWait; + pEventStruct->event.waitingTask->haveToRun = false; /* Cherry-picked from [MCKFW-1872] */ + } + retVal = osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */ + retVal = osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pEventStruct->event.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pEventStruct->event.timeout < OSA_TimeDiff(pEventStruct->event.time_start, currentTime)) + { + pEventStruct->event.isWaiting = false; + retVal = osaStatus_Timeout; + } + } + else if(millisec != osaWaitForever_c) /* If no timeout, don't start the timer */ + { + /* Start the timeout counter */ + pEventStruct->event.isWaiting = true; + pEventStruct->event.time_start = OSA_TimeGetMsec(); + pEventStruct->event.timeout = millisec; + } +#endif + else + { + pEventStruct->event.waitingTask->haveToRun = false; + } + } + + OSA_EnableIRQGlobal(); + + return retVal; +#else + (void)eventId; + (void)flagsToWait; + (void)waitAll; + (void)millisec; + (void)pSetFlags; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventDestroy + * Description : This function is used to destroy a event object. Return + * osaStatus_Success if the event object is destroyed successfully, otherwise + * return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_EventDestroy(osaEventId_t eventId) +{ +#if osNumberOfEvents + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + (void)eventId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQCreate + * Description : This function is used to create a message queue. + * Return : the handle to the message queue if create successfully, otherwise + * return NULL. + * + *END**************************************************************************/ +osaMsgQId_t OSA_MsgQCreate(uint32_t msgNo) +{ +#if osNumberOfMessageQs + osaMsgQId_t msgQId = NULL; + osMsgQStruct_t* pMsgQStruct; + + if(msgNo <= osNumberOfMessages) + { + OSA_InterruptDisable(); + msgQId = pMsgQStruct = osObjectAlloc(&osMsgQInfo); + OSA_InterruptEnable(); + + if(msgQId) + { + pMsgQStruct->queue.max = msgNo; + pMsgQStruct->queue.number = 0; + pMsgQStruct->queue.head = 0; + pMsgQStruct->queue.tail = 0; + } + } + + return msgQId; +#else + msgNo=msgNo; + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQPut + * Description : This function is used to put a message to a message queue. +* Return : osaStatus_Success if the message is put successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, void* pMessage) +{ +#if osNumberOfMessageQs + msg_queue_t* pQueue; + osaStatus_t status = osaStatus_Success; + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + + OSA_DisableIRQGlobal(); + if( pQueue->number >= pQueue->max ) + { + status = osaStatus_Error; + } + else + { + pQueue->queueMem[pQueue->tail] = *((uint32_t*)pMessage); + pQueue->number++; + pQueue->tail++; + + if( pQueue->tail >= pQueue->max ) + { + pQueue->tail = 0; + } + + if( pQueue->waitingTask ) + { + pQueue->waitingTask->haveToRun = 1; + } + } + OSA_EnableIRQGlobal(); + } + + return status; +#else + msgQId=msgQId; + pMessage=pMessage; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQGet + * Description : This function checks the queue's status, if it is not empty, + * get message from it and return osaStatus_Success, otherwise, timeout will + * be used for wait. The parameter timeout indicates how long should wait in + * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return + * osaStatus_Timeout immediately if queue is empty. + * This function returns osaStatus_Success if message is got successfully, + * returns osaStatus_Timeout if message queue is empty within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, void *pMessage, uint32_t millisec) +{ +#if osNumberOfMessageQs + osaStatus_t status = osaStatus_Idle; + msg_queue_t* pQueue; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + pQueue->waitingTask = OSA_TaskGetId(); + + OSA_DisableIRQGlobal(); + if( pQueue->number ) + { + *((uint32_t*)pMessage) = pQueue->queueMem[pQueue->head]; + pQueue->number--; + pQueue->head++; + pQueue->isWaiting = 0; + + if( pQueue->head >= pQueue->max ) + { + pQueue->head = 0; + } + status = osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */ + status = osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pQueue->isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pQueue->timeout < OSA_TimeDiff(pQueue->time_start, currentTime)) + { + pQueue->isWaiting = 0; + status = osaStatus_Timeout; + } + } + else if(millisec != osaWaitForever_c) /* If no timeout, don't start the timer */ + { + /* Start the timeout counter */ + pQueue->isWaiting = 1; + pQueue->time_start = OSA_TimeGetMsec(); + pQueue->timeout = millisec; + } +#endif + else + { + pQueue->waitingTask->haveToRun = 0; + } + } + OSA_EnableIRQGlobal(); + } + + return status; +#else + msgQId=msgQId; + pMessage=pMessage; + millisec=millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EXT_MsgQDestroy + * Description : This function is used to destroy the message queue. + * Return : osaStatus_Success if the message queue is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId) +{ +#if osNumberOfMessageQs + osaStatus_t status = osaStatus_Success; + msg_queue_t* pQueue; + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + + if( pQueue->waitingTask ) + { + pQueue->waitingTask->haveToRun = 1; + pQueue->waitingTask = NULL; + } + + OSA_InterruptDisable(); + osObjectFree(&osMsgQInfo, msgQId); + OSA_InterruptEnable(); + } + + return status; +#else + msgQId=msgQId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptEnable(void) +{ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptDisable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptDisable(void) +{ + OSA_DisableIRQGlobal(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestricted + * Description : Disable interrupts except high-priority ones + * + *END**************************************************************************/ + void OSA_InterruptEnableRestricted(uint32_t *pu32OldIntLevel) +{ + /* Disable interrupts for duration of this function */ + OSA_DisableIRQGlobal(); + + /* Store old priority level */ + *pu32OldIntLevel = __get_BASEPRI(); + + /* Update priority level, but only if it is a more restrictive value */ + __set_BASEPRI_MAX(((3U << (8U - __NVIC_PRIO_BITS)) & 0xffU)); + + /* Restore interrupts */ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestore + * Description : Restore interrupts that were previously restricted by a call + * to OSA_InterruptEnableRestricted + * + *END**************************************************************************/ + void OSA_InterruptEnableRestore(uint32_t *pu32OldIntLevel) +{ + // write value direct into register ARM to ARM, no translations required + __set_BASEPRI(*pu32OldIntLevel); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InstallIntHandler + * Description : This function is used to install interrupt handler. + * + *END**************************************************************************/ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)) +{ +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_suppress = Pm138") +#endif +#ifdef ENABLE_RAM_VECTOR_TABLE + InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t)handler); +#endif +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_remark = PM138") +#endif +} + +/*! ********************************************************************************* +************************************************************************************* +* Private functions +************************************************************************************* +********************************************************************************** */ +#if (osCustomStartup == 0) +OSA_TASK_DEFINE(main_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0); + +int main (void) +{ + extern void hardware_init(void); + + OSA_Init(); + /* Initialize MCU clock */ + hardware_init(); + OSA_TimeInit(); + OSA_TaskCreate(OSA_TASK(main_task),NULL); + OSA_Start(); + + return 0; +} +#endif + +/*! ********************************************************************************* +* \brief Allocates a osObjectStruct_t block in the osObjectHeap array. +* \param[in] pointer to the object info struct. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return Pointer to the allocated osObjectStruct_t, NULL if failed. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++) + { + if(((osObjStruct_t*)pObj)->inUse == 0) + { + ((osObjStruct_t*)pObj)->inUse = 1; + return (void*)pObj; + } + + pObj += pOsObjectInfo->objectStructSize; + } + return NULL; +} +#endif +/*! ********************************************************************************* +* \brief Verifies the object is valid and allocated in the osObjectHeap array. +* \param[in] the pointer to the object info struct. +* \param[in] the pointer to the object struct. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return TRUE if the object is valid and allocated, FALSE otherwise +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++) + { + if(pObj == pObjectStruct) + { + if(((osObjStruct_t*)pObj)->inUse) + { + return TRUE; + } + break; + } + pObj += pOsObjectInfo->objectStructSize; + } + return FALSE; +} +#endif + +/*! ********************************************************************************* +* \brief Frees an osObjectStruct_t block from the osObjectHeap array. +* \param[in] pointer to the object info struct. +* \param[in] Pointer to the allocated osObjectStruct_t to free. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return none. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0; i < pOsObjectInfo->objNo; i++ ) + { + if(pObj == pObjectStruct) + { + ((osObjStruct_t*)pObj)->inUse = 0; + break; + } + + pObj += pOsObjectInfo->objectStructSize; + } +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_Init + * Description : This function is used to setup the basic services, it should + * be called first in function main. Return kStatus_OSA_Success if services + * are initialized successfully, otherwise return kStatus_OSA_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_Init(void) +{ +#if (TASK_MAX_NUM > 0) + task_init(); +#endif + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_Start + * Description : This function is used to start RTOS scheduler. + * + *END**************************************************************************/ +void OSA_Start(void) +{ +#if (TASK_MAX_NUM > 0) + g_curTask = p_taskListHead; + + for(;;) + { + if(g_curTask->haveToRun) + { + if(g_curTask->p_func) + { + g_curTask->p_func(g_curTask->param); + } + /* restart from the first task */ + g_curTask = p_taskListHead; + } + else + { + g_curTask = g_curTask->next; + } + } +#else + for(;;) + { + } +#endif +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InsertTaskBefore + * Description : Helper function to insert Task TCB into the task list. + * + *END**************************************************************************/ +static void OSA_InsertTaskBefore(task_handler_t newTCB, task_handler_t currentTCB) +{ + newTCB->next = currentTCB; + newTCB->prev = currentTCB->prev; + currentTCB->prev->next = newTCB; + currentTCB->prev = newTCB; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : SysTick_Handler + * Description : This ISR of the SYSTICK timer. + * + *END**************************************************************************/ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) +void SysTick_Handler(void) +{ + gTickCounter++; +} +#endif diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c new file mode 100755 index 000000000..906c61e9e --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c @@ -0,0 +1,1173 @@ +/*! ********************************************************************************* +* Copyright (c) 2015, Freescale Semiconductor, Inc. +* Copyright 2016-2017, 2019 NXP +* All rights reserved. +* +* \file +* +* This is the source file for the OS Abstraction layer for freertos. +* +* SPDX-License-Identifier: BSD-3-Clause +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ +#include "EmbeddedTypes.h" +#include "fsl_os_abstraction.h" +#include "fsl_os_abstraction_free_rtos.h" +#include +#include "GenericList.h" +#include "fsl_common.h" +#include "Panic.h" +/*! ********************************************************************************* +************************************************************************************* +* Private macros +************************************************************************************* +********************************************************************************** */ +#define millisecToTicks(millisec) ((millisec * configTICK_RATE_HZ + 999)/1000) + +#ifdef DEBUG_ASSERT +#define OS_ASSERT(condition) if(!(condition))while(1); +#else +#define OS_ASSERT(condition) (void)(condition); +#endif + +#if (osNumberOfEvents) +#define osObjectAlloc_c 1 +#else +#define osObjectAlloc_c 0 +#endif + +/*! @brief Converts milliseconds to ticks*/ +#define MSEC_TO_TICK(msec) (((uint32_t)(msec)+500uL/(uint32_t)configTICK_RATE_HZ) \ + *(uint32_t)configTICK_RATE_HZ/1000uL) +#define TICKS_TO_MSEC(tick) ((uint64_t)(tick)*1000uL/(uint32_t)configTICK_RATE_HZ) +/************************************************************************************ +************************************************************************************* +* Private type definitions +************************************************************************************* +************************************************************************************/ + +typedef struct osEventStruct_tag +{ + uint32_t inUse; + event_t event; +}osEventStruct_t; + +typedef struct osObjStruct_tag +{ + uint32_t inUse; + uint32_t osObj; +}osObjStruct_t; + +typedef struct osObjectInfo_tag +{ + void* pHeap; + uint32_t objectStructSize; + uint32_t objNo; +} osObjectInfo_t; + + +/*! ********************************************************************************* +************************************************************************************* +* Private prototypes +************************************************************************************* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo); +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +#endif +extern void main_task(void const *argument); +extern void hardware_init(void); +void startup_task(void* argument); + + +/*! ********************************************************************************* +************************************************************************************* +* Public memory declarations +************************************************************************************* +********************************************************************************** */ +const uint8_t gUseRtos_c = USE_RTOS; // USE_RTOS = 0 for BareMetal and 1 for OS +static uint32_t g_base_priority_array[OSA_MAX_ISR_CRITICAL_SECTION_DEPTH]; +static int32_t g_base_priority_top = 0; + +/*! ********************************************************************************* +************************************************************************************* +* Private memory declarations +************************************************************************************* +********************************************************************************** */ + +#if osNumberOfEvents +osEventStruct_t osEventHeap[osNumberOfEvents]; +const osObjectInfo_t osEventInfo = {osEventHeap, sizeof(osEventStruct_t),osNumberOfEvents}; +#endif + + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ + +/*FUNCTION********************************************************************** + * + * Function Name : startup_task + * Description : Wrapper over main_task.. + * + *END**************************************************************************/ +void startup_task(void* argument) +{ + main_task(argument); + while(1); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetId + * Description : This function is used to get current active task's handler. + * + *END**************************************************************************/ +osaTaskId_t OSA_TaskGetId(void) +{ + return xTaskGetCurrentTaskHandle(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskYield + * Description : When a task calls this function, it will give up CPU and put + * itself to the tail of ready list. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskYield(void) +{ + taskYIELD(); + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetPriority + * Description : This function returns task's priority by task handler. + * + *END**************************************************************************/ +osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId) +{ + return (osaTaskPriority_t)(PRIORITY_RTOS_TO_OSA(uxTaskPriorityGet((task_handler_t)taskId))); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskSetPriority + * Description : This function sets task's priority by task handler. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority) +{ + vTaskPrioritySet((task_handler_t)taskId, PRIORITY_OSA_TO_RTOS(taskPriority)); + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** +* +* Function Name : OSA_TaskCreate +* Description : This function is used to create a task and make it ready. +* Param[in] : threadDef - Definition of the thread. +* task_param - Parameter to pass to the new thread. +* Return Thread handle of the new thread, or NULL if failed. +* +*END**************************************************************************/ +osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def,osaTaskParam_t task_param) +{ + osaTaskId_t taskId = NULL; + task_handler_t task_handler; + + if (xTaskCreate( + (task_t)thread_def->pthread, /* pointer to the task */ + (char const*)thread_def->tname, /* task name for kernel awareness debugging */ + thread_def->stacksize/sizeof(portSTACK_TYPE), /* task stack size */ + (task_param_t)task_param, /* optional task startup argument */ + PRIORITY_OSA_TO_RTOS(thread_def->tpriority), /* initial priority */ + &task_handler /* optional task handle to create */ + ) == pdPASS) + { + taskId = (osaTaskId_t)task_handler; + } + return taskId; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskDestroy + * Description : This function destroy a task. + * Param[in] :taskId - Thread handle. + * Return osaStatus_Success if the task is destroied, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId) +{ + osaStatus_t status; + uint16_t oldPriority; + /*Change priority to avoid context switches*/ + oldPriority = OSA_TaskGetPriority(OSA_TaskGetId()); + (void)OSA_TaskSetPriority(OSA_TaskGetId(), OSA_PRIORITY_REAL_TIME); +#if INCLUDE_vTaskDelete /* vTaskDelete() enabled */ + vTaskDelete((task_handler_t)taskId); + status = osaStatus_Success; +#else + status = osaStatus_Error; /* vTaskDelete() not available */ +#endif + (void)OSA_TaskSetPriority(OSA_TaskGetId(), oldPriority); + + return status; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeDelay + * Description : This function is used to suspend the active thread for the given number of milliseconds. + * + *END**************************************************************************/ +void OSA_TimeDelay(uint32_t millisec) +{ + vTaskDelay(millisecToTicks(millisec)); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeGetMsec + * Description : This function gets current time in milliseconds. + * + *END**************************************************************************/ +uint32_t OSA_TimeGetMsec(void) +{ + portTickType ticks; + + if (__get_IPSR()) + { + ticks = xTaskGetTickCountFromISR(); + } + else + { + ticks = xTaskGetTickCount(); + } + + return TICKS_TO_MSEC(ticks); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreCreate + * Description : This function is used to create a semaphore. + * Return : Semaphore handle of the new semaphore, or NULL if failed. + * + *END**************************************************************************/ +osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue) +{ +#if osNumberOfSemaphores + semaphore_t sem; + sem = xSemaphoreCreateCounting(0xFF, initValue); + return (osaSemaphoreId_t)sem; +#else + (void)initValue; + return NULL; +#endif + +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreDestroy + * Description : This function is used to destroy a semaphore. + * Return : osaStatus_Success if the semaphore is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + semaphore_t sem = (semaphore_t)semId; + if(sem == NULL) + { + return osaStatus_Error; + } + vSemaphoreDelete(sem); + return osaStatus_Success; +#else + (void)semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreWait + * Description : This function checks the semaphore's counting value, if it is + * positive, decreases it and returns osaStatus_Success, otherwise, timeout + * will be used for wait. The parameter timeout indicates how long should wait + * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will + * return osaStatus_Timeout immediately if semaphore is not positive. + * This function returns osaStatus_Success if the semaphore is received, returns + * osaStatus_Timeout if the semaphore is not received within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) +{ +#if osNumberOfSemaphores + uint32_t timeoutTicks; + if(semId == NULL) + { + return osaStatus_Error; + } + semaphore_t sem = (semaphore_t)semId; + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + + if (xSemaphoreTake(sem, timeoutTicks)==pdFALSE) + { + return osaStatus_Timeout; /* timeout */ + } + else + { + return osaStatus_Success; /* semaphore taken */ + } +#else + (void)semId; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphorePost + * Description : This function is used to wake up one task that wating on the + * semaphore. If no task is waiting, increase the semaphore. The function returns + * osaStatus_Success if the semaphre is post successfully, otherwise returns + * osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + osaStatus_t status = osaStatus_Error; + if(semId) + { + semaphore_t sem = (semaphore_t)semId; + + if (__get_IPSR()) + { + portBASE_TYPE taskToWake = pdFALSE; + + if (pdTRUE==xSemaphoreGiveFromISR(sem, &taskToWake)) + { + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + status = osaStatus_Success; + } + else + { + status = osaStatus_Error; + } + } + else + { + if (pdTRUE == xSemaphoreGive(sem)) + { + status = osaStatus_Success; /* sync object given */ + } + else + { + status = osaStatus_Error; + } + } + } + return status; +#else + (void)semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexCreate + * Description : This function is used to create a mutex. + * Return : Mutex handle of the new mutex, or NULL if failed. + * + *END**************************************************************************/ +osaMutexId_t OSA_MutexCreate(void) +{ +#if osNumberOfMutexes + mutex_t mutex; + mutex = xSemaphoreCreateMutex(); + return (osaMutexId_t)mutex; +#else + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexLock + * Description : This function checks the mutex's status, if it is unlocked, + * lock it and returns osaStatus_Success, otherwise, wait for the mutex. + * This function returns osaStatus_Success if the mutex is obtained, returns + * osaStatus_Error if any errors occur during waiting. If the mutex has been + * locked, pass 0 as timeout will return osaStatus_Timeout immediately. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) +{ +#if osNumberOfMutexes + uint32_t timeoutTicks; + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + /* If pMutex has been locked by current task, return error. */ + if (xSemaphoreGetMutexHolder(mutex) == xTaskGetCurrentTaskHandle()) + { + return osaStatus_Error; + } + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + + if (xSemaphoreTake(mutex, timeoutTicks)==pdFALSE) + { + return osaStatus_Timeout; /* timeout */ + } + else + { + return osaStatus_Success; /* semaphore taken */ + } +#else + (void)mutexId; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexUnlock + * Description : This function is used to unlock a mutex. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + /* If pMutex is not locked by current task, return error. */ + if (xSemaphoreGetMutexHolder(mutex) != xTaskGetCurrentTaskHandle()) + { + return osaStatus_Error; + } + + if (xSemaphoreGive(mutex)==pdPASS) + { + return osaStatus_Success; + } + else + { + return osaStatus_Error; + } +#else + (void)mutexId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexDestroy + * Description : This function is used to destroy a mutex. + * Return : osaStatus_Success if the lock object is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + vSemaphoreDelete(mutex); + return osaStatus_Success; +#else + (void)mutexId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventCreate + * Description : This function is used to create a event object. + * Return : Event handle of the new event, or NULL if failed. + * + *END**************************************************************************/ +osaEventId_t OSA_EventCreate(bool_t autoClear) +{ +#if osNumberOfEvents + osaEventId_t eventId; + osEventStruct_t* pEventStruct; + OSA_InterruptDisable(); + eventId = pEventStruct = osObjectAlloc(&osEventInfo); + OSA_InterruptEnable(); + if(eventId == NULL) + { + return NULL; + } + + pEventStruct->event.eventHandler = xEventGroupCreate(); + if (pEventStruct->event.eventHandler) + { + pEventStruct->event.autoClear = autoClear; + } + else + { + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + eventId = NULL; + } + return eventId; +#else + (void)autoClear; + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventSet + * Description : Set one or more event flags of an event object. + * Return : osaStatus_Success if set successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + portBASE_TYPE taskToWake = pdFALSE; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + if (__get_IPSR()) + { + if (pdPASS != xEventGroupSetBitsFromISR(pEventStruct->event.eventHandler, (event_flags_t)flagsToSet, &taskToWake)) + { + panic(0,(uint32_t)OSA_EventSet,0,0); + return osaStatus_Error; + } + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + } + else + { + xEventGroupSetBits(pEventStruct->event.eventHandler, (event_flags_t)flagsToSet); + } + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToSet; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventClear + * Description : Clear one or more event flags of an event object. + * Return :osaStatus_Success if clear successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear) +{ +#if osNumberOfEvents + + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + + if (__get_IPSR()) + { + xEventGroupClearBitsFromISR(pEventStruct->event.eventHandler, (event_flags_t)flagsToClear); + } + else + { + xEventGroupClearBits(pEventStruct->event.eventHandler, (event_flags_t)flagsToClear); + } + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToClear; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventWait + * Description : This function checks the event's status, if it meets the wait + * condition, return osaStatus_Success, otherwise, timeout will be used for + * wait. The parameter timeout indicates how long should wait in milliseconds. + * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value + * osaStatus_Timeout immediately if wait condition is not met. The event flags + * will be cleared if the event is auto clear mode. Flags that wakeup waiting + * task could be obtained from the parameter setFlags. + * This function returns osaStatus_Success if wait condition is met, returns + * osaStatus_Timeout if wait condition is not met within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + BaseType_t clearMode; + uint32_t timeoutTicks; + event_flags_t flagsSave; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + + /* Clean FreeRTOS cotrol flags */ + flagsToWait = flagsToWait & 0x00FFFFFF; + + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = millisec/portTICK_PERIOD_MS; + } + + clearMode = (pEventStruct->event.autoClear) ? pdTRUE: pdFALSE; + + flagsSave = xEventGroupWaitBits(pEventStruct->event.eventHandler,(event_flags_t)flagsToWait,clearMode,(BaseType_t)waitAll,timeoutTicks); + + flagsSave &= (event_flags_t)flagsToWait; + if(pSetFlags) + { + *pSetFlags = (osaEventFlags_t)flagsSave; + } + + if (flagsSave) + { + return osaStatus_Success; + } + else + { + return osaStatus_Timeout; + } +#else + (void)eventId; + (void)flagsToWait; + (void)waitAll; + (void)millisec; + (void)pSetFlags; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventDestroy + * Description : This function is used to destroy a event object. Return + * osaStatus_Success if the event object is destroyed successfully, otherwise + * return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_EventDestroy(osaEventId_t eventId) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + vEventGroupDelete(pEventStruct->event.eventHandler); + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + (void)eventId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQCreate + * Description : This function is used to create a message queue. + * Return : the handle to the message queue if create successfully, otherwise + * return NULL. + * + *END**************************************************************************/ +osaMsgQId_t OSA_MsgQCreate( uint32_t msgNo ) +{ +#if osNumberOfMessageQs + msg_queue_handler_t msg_queue_handler; + + /* Create the message queue where each element is a pointer to the message item. */ + msg_queue_handler = xQueueCreate(msgNo,sizeof(osaMsg_t)); + return (osaMsgQId_t)msg_queue_handler; +#else + (void)msgNo; + return NULL; +#endif +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQPut + * Description : This function is used to put a message to a message queue. +* Return : osaStatus_Success if the message is put successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, void* pMessage) +{ +#if osNumberOfMessageQs + msg_queue_handler_t handler; + osaStatus_t osaStatus; + if(msgQId == NULL) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + { + if (__get_IPSR()) + { + portBASE_TYPE taskToWake = pdFALSE; + + if (pdTRUE == xQueueSendToBackFromISR(handler, pMessage, &taskToWake)) + { + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + osaStatus = osaStatus_Success; + } + else + { + osaStatus = osaStatus_Error; + } + + } + else + { + osaStatus = (xQueueSendToBack(handler, pMessage, 0)== pdPASS)?(osaStatus_Success):(osaStatus_Error); + } + } + return osaStatus; +#else + (void)msgQId; + (void)pMessage; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQGet + * Description : This function checks the queue's status, if it is not empty, + * get message from it and return osaStatus_Success, otherwise, timeout will + * be used for wait. The parameter timeout indicates how long should wait in + * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return + * osaStatus_Timeout immediately if queue is empty. + * This function returns osaStatus_Success if message is got successfully, + * returns osaStatus_Timeout if message queue is empty within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, void *pMessage, uint32_t millisec) +{ +#if osNumberOfMessageQs + osaStatus_t osaStatus; + msg_queue_handler_t handler; + uint32_t timeoutTicks; + if( msgQId == NULL ) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + if (xQueueReceive(handler, pMessage, timeoutTicks)!=pdPASS) + { + osaStatus = osaStatus_Timeout; /* not able to send it to the queue? */ + } + else + { + osaStatus = osaStatus_Success; + } + return osaStatus; +#else + (void)msgQId; + (void)pMessage; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQDestroy + * Description : This function is used to destroy the message queue. + * Return : osaStatus_Success if the message queue is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId) +{ +#if osNumberOfMessageQs + msg_queue_handler_t handler; + if(msgQId == NULL ) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + vQueueDelete(handler); + return osaStatus_Success; +#else + (void)msgQId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptEnable(void) +{ + if (__get_IPSR()) + { + if(g_base_priority_top) + { + g_base_priority_top--; + portCLEAR_INTERRUPT_MASK_FROM_ISR(g_base_priority_array[g_base_priority_top]); + } + + } + else + { + portEXIT_CRITICAL(); + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptDisable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptDisable(void) +{ + if (__get_IPSR()) + { + if(g_base_priority_top < OSA_MAX_ISR_CRITICAL_SECTION_DEPTH) + { + g_base_priority_array[g_base_priority_top] = portSET_INTERRUPT_MASK_FROM_ISR(); + g_base_priority_top++; + } + + } + else + { + portENTER_CRITICAL(); + } + +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestricted + * Description : Disable interrupts except high-priority ones + * + *END**************************************************************************/ +void OSA_InterruptEnableRestricted(uint32_t *pu8OldIntLevel) +{ + /* Disable interrupts for duration of this function */ + OSA_DisableIRQGlobal(); + + /* Store old priority level */ + *pu8OldIntLevel = __get_BASEPRI(); + + /* Update priority level, but only if it is a more restrictive value */ + __set_BASEPRI_MAX((3U << (8U - __NVIC_PRIO_BITS)) & 0xffU); + + /* Restore interrupts */ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestore + * Description : Restore interrupts that were previously restricted by a call + * to OSA_InterruptEnableRestricted + * + *END**************************************************************************/ +void OSA_InterruptEnableRestore(uint32_t *pu8OldIntLevel) +{ + // write value direct into register ARM to ARM, no translations required + __set_BASEPRI(*pu8OldIntLevel); +} + + +uint32_t gInterruptDisableCount = 0; +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EnableIRQGlobal + * Description : enable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_EnableIRQGlobal(void) +{ + if (gInterruptDisableCount > 0) + { + gInterruptDisableCount--; + + if (gInterruptDisableCount == 0) + { + __enable_irq(); + } + /* call core API to enable the global interrupt*/ + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_DisableIRQGlobal + * Description : disable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_DisableIRQGlobal(void) +{ + /* call core API to disable the global interrupt*/ + __disable_irq(); + + /* update counter*/ + gInterruptDisableCount++; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InstallIntHandler + * Description : This function is used to install interrupt handler. + * + *END**************************************************************************/ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)) +{ + +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_suppress = Pm138") +#endif + InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t)handler); +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_remark = PM138") +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeInit + * Description : Empty + * + *END**************************************************************************/ +void OSA_TimeInit(void) +{ + +} + +/*! ********************************************************************************* +************************************************************************************* +* Private functions +************************************************************************************* +********************************************************************************** */ +OSA_TASK_DEFINE(startup_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0) ; +int main (void) +{ + /* Initialize MCU clock */ + hardware_init(); + OSA_TaskCreate(OSA_TASK(startup_task), NULL); + vTaskStartScheduler(); + + return 0; +} + +/*! ********************************************************************************* +* \brief Allocates a osObjectStruct_t block in the osObjectHeap array. +* \param[in] pointer to the object info struct. +* Object can be semaphore, mutex, message Queue, event +* \return Pointer to the allocated osObjectStruct_t, NULL if failed. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++, pObj += pOsObjectInfo->objectStructSize) + { + if(((osObjStruct_t*)pObj)->inUse == 0) + { + ((osObjStruct_t*)pObj)->inUse = 1; + return (void*)pObj; + } + } + return NULL; +} +#endif + +/*! ********************************************************************************* +* \brief Verifies the object is valid and allocated in the osObjectHeap array. +* \param[in] the pointer to the object info struct. +* \param[in] the pointer to the object struct. +* Object can be semaphore, mutex, message Queue, event +* \return TRUE if the object is valid and allocated, FALSE otherwise +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++ , pObj += pOsObjectInfo->objectStructSize) + { + if(pObj == pObjectStruct) + { + if(((osObjStruct_t*)pObj)->inUse) + { + return TRUE; + } + break; + } + } + return FALSE; +} +#endif + +/*! ********************************************************************************* +* \brief Frees an osObjectStruct_t block from the osObjectHeap array. +* \param[in] pointer to the object info struct. +* \param[in] Pointer to the allocated osObjectStruct_t to free. +* Object can be semaphore, mutex, message Queue, event +* \return none. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0; i < pOsObjectInfo->objNo; i++, pObj += pOsObjectInfo->objectStructSize ) + { + if(pObj == pObjectStruct) + { + ((osObjStruct_t*)pObj)->inUse = 0; + break; + } + } +} +#endif + +/*! ********************************************************************************* +* \brief FreeRTOS application malloc failed hook +* +* +* \remarks Function is called by FreeRTOS if there is not enough space in the +* heap for task stack allocation or for OS object allocation +* +********************************************************************************** */ +#if (configUSE_MALLOC_FAILED_HOOK==1) +void vApplicationMallocFailedHook (void) +{ + panic(0,(uint32_t)vApplicationMallocFailedHook,0,0); +} +#endif + diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Include/PDM.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Include/PDM.h new file mode 100755 index 000000000..a1650ab86 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Include/PDM.h @@ -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 ***/ +/****************************************************************************/ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Library/libPDM.a b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Library/libPDM.a new file mode 100755 index 000000000..9c40aac91 Binary files /dev/null and b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/Library/libPDM.a differ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/PDM.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/PDM.h new file mode 100755 index 000000000..a2b8f1001 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/PDM.h @@ -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 ***/ +/****************************************************************************/ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/pdm_port.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/pdm_port.c new file mode 100755 index 000000000..770a93106 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/PDM/pdm_port.c @@ -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 +#include +#include + +#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; +} +/*-----------------------------------------------------------*/ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Interface/Panic.h b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Interface/Panic.h new file mode 100755 index 000000000..aa65ec716 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Interface/Panic.h @@ -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__ */ diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Source/Panic.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Source/Panic.c new file mode 100755 index 000000000..8315b0c1a --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Panic/Source/Panic.c @@ -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 diff --git a/third_party/nxp/JN5189DK6/middleware/wireless/framework/Reset/Reset.c b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Reset/Reset.c new file mode 100755 index 000000000..9fa25ce27 --- /dev/null +++ b/third_party/nxp/JN5189DK6/middleware/wireless/framework/Reset/Reset.c @@ -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 ***************************************/ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c new file mode 100755 index 000000000..2f55db224 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.c @@ -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 */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h new file mode 100755 index 000000000..9c89723ce --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Flash/Internal/Flash_Adapter.h @@ -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__ */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c new file mode 100755 index 000000000..5e6b88ad6 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.c @@ -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 +#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 diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h new file mode 100755 index 000000000..047b2fd77 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/FunctionLib/FunctionLib.h @@ -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 + +/*! ********************************************************************************* +************************************************************************************* +* 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< (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_ */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.c new file mode 100755 index 000000000..21ea993b0 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.c @@ -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; ihead == 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 + diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.h new file mode 100755 index 000000000..a094ce9bd --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Lists/GenericList.h @@ -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_*/ \ No newline at end of file diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h new file mode 100755 index 000000000..f9e6fb5b8 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Interface/MemManager.h @@ -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 + +#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_ */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Source/MemManager.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Source/MemManager.c new file mode 100755 index 000000000..903d473dc --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/MemManager/Source/MemManager.c @@ -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; iallocStatus == 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; ipoolSize; 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); +} diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h new file mode 100755 index 000000000..0f8b2c21a --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction.h @@ -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 diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h new file mode 100755 index 000000000..1578be2e4 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_bm.h @@ -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 + ******************************************************************************/ + diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h new file mode 100755 index 000000000..d74baaf99 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_config.h @@ -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_ */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h new file mode 100755 index 000000000..c1ba29243 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Interface/fsl_os_abstraction_free_rtos.h @@ -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 + ******************************************************************************/ + diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c new file mode 100755 index 000000000..bb5fc93e3 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_bm.c @@ -0,0 +1,1527 @@ +/*! ********************************************************************************* +* Copyright (c) 2015, Freescale Semiconductor, Inc. +* Copyright 2016-2017 NXP +* All rights reserved. +* +* \file +* +* This is the source file for the OS Abstraction layer for MQXLite. +* +* SPDX-License-Identifier: BSD-3-Clause +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ + +#include "EmbeddedTypes.h" +#include "fsl_os_abstraction.h" +#include "fsl_os_abstraction_bm.h" +#include "fsl_common.h" +#include +#include "GenericList.h" + +/*! ********************************************************************************* +************************************************************************************* +* Private macros +************************************************************************************* +********************************************************************************** */ + +/* Weak function. */ +#if defined(__GNUC__) +#define __WEAK_FUNC __attribute__((weak)) +#elif defined(__ICCARM__) +#define __WEAK_FUNC __weak +#elif defined( __CC_ARM ) +#define __WEAK_FUNC __weak +#endif + +#ifdef DEBUG_ASSERT +#define OS_ASSERT(condition) if(!(condition))while(1); +#else +#define OS_ASSERT(condition) (void)(condition); +#endif + +#if (osNumberOfSemaphores || osNumberOfMutexes || osNumberOfEvents || osNumberOfMessageQs) +#define osObjectAlloc_c 1 +#else +#define osObjectAlloc_c 0 +#endif + +/************************************************************************************ +************************************************************************************* +* Private type definitions +************************************************************************************* +************************************************************************************/ + +typedef struct osMutexStruct_tag + { + uint32_t inUse; + mutex_t mutex; + }osMutexStruct_t; + +typedef struct osEventStruct_tag + { + uint32_t inUse; + event_t event; + }osEventStruct_t; + +typedef struct osSemaphoreStruct_tag + { + uint32_t inUse; + semaphore_t semaphore; + }osSemaphoreStruct_t; + +typedef struct osMsgQStruct_tag + { + uint32_t inUse; + msg_queue_t queue; + }osMsgQStruct_t; + +typedef struct osObjStruct_tag + { + uint32_t inUse; + uint32_t osObj; + }osObjStruct_t; + +typedef struct osObjectInfo_tag +{ + void* pHeap; + uint32_t objectStructSize; + uint32_t objNo; +}osObjectInfo_t; + + +/*! ********************************************************************************* +************************************************************************************* +* Private prototypes +************************************************************************************* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo); +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +#endif + +extern void main_task(void *argument); +void task_init(void); +__WEAK_FUNC void OSA_TimeInit(void); +__WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end); +osaStatus_t OSA_Init(void); +void OSA_Start(void); +static void OSA_InsertTaskBefore(task_handler_t newTCB, task_handler_t currentTCB); + +/*! ********************************************************************************* +************************************************************************************* +* Public memory declarations +************************************************************************************* +********************************************************************************** */ +#define main_taskStack NULL + +const uint8_t gUseRtos_c = USE_RTOS; /* USE_RTOS = 0 for BareMetal and 1 for OS */ + +/*! ********************************************************************************* +************************************************************************************* +* Private memory declarations +************************************************************************************* +********************************************************************************** */ + +list_t threadList; + +#if osNumberOfSemaphores +osSemaphoreStruct_t osSemaphoreHeap[osNumberOfSemaphores]; +const osObjectInfo_t osSemaphoreInfo = {osSemaphoreHeap, sizeof(osSemaphoreStruct_t),osNumberOfSemaphores}; +#endif + +#if osNumberOfMutexes +osMutexStruct_t osMutexHeap[osNumberOfMutexes]; +const osObjectInfo_t osMutexInfo = {osMutexHeap, sizeof(osMutexStruct_t),osNumberOfMutexes}; +#endif + +#if osNumberOfEvents +osEventStruct_t osEventHeap[osNumberOfEvents]; +const osObjectInfo_t osEventInfo = {osEventHeap, sizeof(osEventStruct_t),osNumberOfEvents}; +#endif + +#if osNumberOfMessageQs +osMsgQStruct_t osMsgQHeap[osNumberOfMessageQs]; +const osObjectInfo_t osMsgQInfo = {osMsgQHeap, sizeof(osMsgQStruct_t),osNumberOfMessageQs}; +#endif + +#if (TASK_MAX_NUM > 0) + +/* Global variales for task. */ +static task_handler_t g_curTask; /* Current task. */ +/* + * All task control blocks in g_taskControlBlockPool will be linked as a + * list, and the list is managed by the pointer g_freeTaskControlBlock. + */ +static task_control_block_t g_taskControlBlockPool[TASK_MAX_NUM]; + +/* + * Pointer to the free task control blocks. To create a task, we should get + * task control block from this pointer. When task is destroyed, the control + * block will be returned and managed by this pointer. + */ +static task_control_block_t *g_freeTaskControlBlock; + +/* Head node of task list, all tasks will be linked to this head node. */ +static task_control_block_t *p_taskListHead = NULL; +#endif +uint32_t gInterruptDisableCount = 0; +uint32_t gTickCounter = 0; + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EnableIRQGlobal + * Description : Disable system interrupt. + * + *END**************************************************************************/ +void OSA_EnableIRQGlobal(void) +{ + if (gInterruptDisableCount > 0) + { + gInterruptDisableCount--; + + if (gInterruptDisableCount == 0) + { + __enable_irq(); + } + /* call core API to enable the global interrupt*/ + } +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_DisableIRQGlobal + * Description : Disable system interrupt + * This function will disable the global interrupt by calling the core API + * + *END**************************************************************************/ +void OSA_DisableIRQGlobal(void) +{ + /* call core API to disable the global interrupt*/ + __disable_irq(); + + /* update counter*/ + gInterruptDisableCount++; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetId + * Description : This function is used to get current active task's handler. + * + *END**************************************************************************/ + +osaTaskId_t OSA_TaskGetId(void) +{ + return (osaTaskId_t)g_curTask; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EXT_TaskYield + * Description : When a task calls this function, it will give up CPU and put + * itself to the tail of ready list. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskYield(void) +{ + return osaStatus_Success; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetPriority + * Description : This function returns task's priority by task handler. + * + *END**************************************************************************/ + +osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId) +{ + task_handler_t handler = (task_handler_t)taskId; + return handler->priority; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskSetPriority + * Description : This function sets task's priority by task handler. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority) +{ + task_handler_t handler = (task_handler_t)taskId; + task_handler_t p; + + /* Remove task control block from task list. */ + handler->prev->next = handler->next; + handler->next->prev = handler->prev; + if( handler == p_taskListHead ) + { + p_taskListHead = handler->next; + } + + handler->priority = taskPriority; + /* Insert task control block into the task list. */ + if( handler->priority <= p_taskListHead->priority ) + { + /* New task has the highest priority */ + OSA_InsertTaskBefore(handler, p_taskListHead); + p_taskListHead = handler; + } + else if( handler->priority >= p_taskListHead->prev->priority ) + { + /* New task has the lowest priority */ + OSA_InsertTaskBefore(handler, p_taskListHead); + } + else + { + p = p_taskListHead->next; + + while (p != p_taskListHead) + { + if (handler->priority <= p->priority) + { + OSA_InsertTaskBefore(handler, p); + break; + } + p = p->next; + } + } + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : task_init + * Description : This function is used to initialize bare metal's task system, + * it will prepare task control block pool and initialize corresponding + * structures. This function should be called before creating any tasks. + * + *END**************************************************************************/ +void task_init(void) +{ + int32_t i = TASK_MAX_NUM-1; + + g_taskControlBlockPool[i].next = NULL; + + while (i--) + { + /* Link all task control blocks to a list. */ + g_taskControlBlockPool[i].next = &g_taskControlBlockPool[i+1]; + } + + g_freeTaskControlBlock = g_taskControlBlockPool; +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskCreate + * Description : This function is used to create a task and make it ready. + * Param[in] : threadDef - Definition of the thread. + * task_param - Parameter to pass to the new thread. + * Return Thread handle of the new thread, or NULL if failed. + * + *END**************************************************************************/ +osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def,osaTaskParam_t task_param) +{ + osaTaskId_t taskId = NULL; + task_control_block_t *p_newTaskControlBlock; + task_control_block_t *p_currentTaskControlBlock; + + if (g_freeTaskControlBlock) + { + /* Get new task control block from pool. */ + p_newTaskControlBlock = g_freeTaskControlBlock; + g_freeTaskControlBlock = g_freeTaskControlBlock->next; + /* Set task entry and parameter.*/ + p_newTaskControlBlock->p_func = thread_def->pthread; + p_newTaskControlBlock->haveToRun = true; + p_newTaskControlBlock->priority = PRIORITY_OSA_TO_RTOS(thread_def->tpriority); + p_newTaskControlBlock->param = task_param; + p_newTaskControlBlock->next = NULL; + p_newTaskControlBlock->prev = NULL; + + if (p_taskListHead == NULL) + { + p_taskListHead = p_newTaskControlBlock; + p_taskListHead->next = p_taskListHead; + p_taskListHead->prev = p_taskListHead; + } + else if (p_newTaskControlBlock->priority <= p_taskListHead->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_taskListHead); + p_taskListHead = p_newTaskControlBlock; + } + else if (p_newTaskControlBlock->priority >= p_taskListHead->prev->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_taskListHead); + } + else + { + p_currentTaskControlBlock = p_taskListHead->next; + + while (p_currentTaskControlBlock != p_taskListHead) + { + if (p_newTaskControlBlock->priority <= p_currentTaskControlBlock->priority) + { + OSA_InsertTaskBefore(p_newTaskControlBlock, p_currentTaskControlBlock); + break; + } + p_currentTaskControlBlock = p_currentTaskControlBlock->next; + } + + } + /* Task handler is pointer of task control block. */ + taskId = (osaTaskId_t)p_newTaskControlBlock; + } + + return taskId; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskDestroy + * Description : This function destroy a task. + * Param[in] :taskId - Thread handle. + * Return osaStatus_Success if the task is destroied, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId) +{ + task_handler_t handler; + if(taskId == NULL) + { + return osaStatus_Error; + } + handler = (task_handler_t)taskId; + + /* Remove task control block from task list. */ + handler->prev->next = handler->next; + handler->next->prev = handler->prev; + + /* + * If current task is destroyed, then g_curTask will point to the previous + * task, so that the subsequent tasks could be called. Check the function + * OSA_Start for more details. + */ + if (handler == g_curTask) + { + g_curTask = handler->prev; + } + + /* Put task control block back to pool. */ + handler->prev = NULL; + handler->next = g_freeTaskControlBlock; + g_freeTaskControlBlock = handler; + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeInit + * Description : This function initializes the timer used in BM OSA, the + * functions such as OSA_TimeDelay, OSA_TimeGetMsec, and the timeout are all + * based on this timer. + * + *END**************************************************************************/ +__WEAK_FUNC void OSA_TimeInit(void) +{ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk); + SysTick->LOAD = SystemCoreClock/1000 - 1; + SysTick->VAL = 0; + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeDiff + * Description : This function gets the difference between two time stamp, + * time overflow is considered. + * + *END**************************************************************************/ +__WEAK_FUNC uint32_t OSA_TimeDiff(uint32_t time_start, uint32_t time_end) +{ + if (time_end >= time_start) + { + return time_end - time_start; + } + else + { + return FSL_OSA_TIME_RANGE - time_start + time_end + 1; + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA__TimeDelay + * Description : This function is used to suspend the active thread for the given number of milliseconds. + * + *END**************************************************************************/ +void OSA_TimeDelay(uint32_t millisec) +{ + uint32_t currTime, timeStart; + + timeStart = OSA_TimeGetMsec(); + + do { + currTime = OSA_TimeGetMsec(); /* Get current time stamp */ + } while (millisec >= OSA_TimeDiff(timeStart, currTime)); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeGetMsec + * Description : This function gets current time in milliseconds. + * + *END**************************************************************************/ +__WEAK_FUNC uint32_t OSA_TimeGetMsec(void) +{ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + return gTickCounter; +#else + return 0; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeResetMsec + * Description : This function resets the current time to 0. + * + *END**************************************************************************/ +__WEAK_FUNC void OSA_TimeResetMsec(void) +{ + gTickCounter = 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreCreate + * Description : This function is used to create a semaphore. + * Return : Semaphore handle of the new semaphore, or NULL if failed. + * + *END**************************************************************************/ + +osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue) +{ +#if osNumberOfSemaphores + osaSemaphoreId_t semId; + osSemaphoreStruct_t* pSemStruct; + OSA_InterruptDisable(); + semId = pSemStruct = osObjectAlloc(&osSemaphoreInfo); + OSA_InterruptEnable(); + if(semId == NULL) + { + return NULL; + } + + pSemStruct->semaphore.semCount = initValue; + pSemStruct->semaphore.isWaiting = false; + pSemStruct->semaphore.time_start = 0u; + pSemStruct->semaphore.timeout = 0u; + + return semId; +#else + initValue=initValue; + return NULL; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreDestroy + * Description : This function is used to destroy a semaphore. + * Return : osaStatus_Success if the semaphore is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + OSA_InterruptDisable(); + osObjectFree(&osSemaphoreInfo, semId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + semId=semId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreWait + * Description : This function checks the semaphore's counting value, if it is + * positive, decreases it and returns osaStatus_Success, otherwise, timeout + * will be used for wait. The parameter timeout indicates how long should wait + * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will + * return osaStatus_Timeout immediately if semaphore is not positive. + * This function returns osaStatus_Success if the semaphore is received, returns + * osaStatus_Timeout if the semaphore is not received within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) +{ +#if osNumberOfSemaphores + osSemaphoreStruct_t* pSemStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + pSemStruct = (osSemaphoreStruct_t*)semId; + /* Check the sem count first. Deal with timeout only if not already set */ + + if (pSemStruct->semaphore.semCount) + { + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.semCount --; + pSemStruct->semaphore.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and semaphore is not available, return kStatus_OSA_Timeout. */ + return osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pSemStruct->semaphore.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pSemStruct->semaphore.timeout < OSA_TimeDiff(pSemStruct->semaphore.time_start, currentTime)) + { + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Timeout; + } + } + else if (millisec != osaWaitForever_c) /* If don't wait forever, start the timer */ + { + /* Start the timeout counter */ + OSA_DisableIRQGlobal(); + pSemStruct->semaphore.isWaiting = true; + OSA_EnableIRQGlobal(); + pSemStruct->semaphore.time_start = OSA_TimeGetMsec(); + pSemStruct->semaphore.timeout = millisec; + } +#endif + } + + return osaStatus_Idle; +#else + semId=semId; + millisec=millisec; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphorePost + * Description : This function is used to wake up one task that wating on the + * semaphore. If no task is waiting, increase the semaphore. The function returns + * osaStatus_Success if the semaphre is post successfully, otherwise returns + * osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + osSemaphoreStruct_t* pSemStruct; + if(osObjectIsAllocated(&osSemaphoreInfo, semId) == FALSE) + { + return osaStatus_Error; + } + pSemStruct = (osSemaphoreStruct_t*)semId; + /* The max value is 0xFF */ + if (0xFF == pSemStruct->semaphore.semCount) + { + return osaStatus_Error; + } + OSA_DisableIRQGlobal(); + ++pSemStruct->semaphore.semCount; + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + semId=semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexCreate + * Description : This function is used to create a mutex. + * Return : Mutex handle of the new mutex, or NULL if failed. + * + *END**************************************************************************/ +osaMutexId_t OSA_MutexCreate(void) +{ +#if osNumberOfMutexes + osaMutexId_t mutexId; + osMutexStruct_t* pMutexStruct; + OSA_InterruptDisable(); + mutexId = pMutexStruct = osObjectAlloc(&osMutexInfo); + OSA_InterruptEnable(); + if(mutexId == NULL) + { + return NULL; + } + pMutexStruct->mutex.isLocked = false; + pMutexStruct->mutex.isWaiting = false; + pMutexStruct->mutex.time_start = 0u; + pMutexStruct->mutex.timeout = 0u; + return mutexId; +#else + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexLock + * Description : This function checks the mutex's status, if it is unlocked, + * lock it and returns osaStatus_Success, otherwise, wait for the mutex. + * MQX does not support timeout to wait for a mutex. + * This function returns osaStatus_Success if the mutex is obtained, returns + * osaStatus_Error if any errors occur during waiting. If the mutex has been + * locked, pass 0 as timeout will return osaStatus_Timeout immediately. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) +{ +#if osNumberOfMutexes + osMutexStruct_t* pMutexStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + pMutexStruct = (osMutexStruct_t*)mutexId; + + /* Always check first. Deal with timeout only if not available. */ + if (pMutexStruct->mutex.isLocked == false) + { + /* Get the lock and return success */ + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isLocked = true; + pMutexStruct->mutex.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and mutex is not available, return kStatus_OSA_Timeout. */ + return osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pMutexStruct->mutex.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pMutexStruct->mutex.timeout < OSA_TimeDiff(pMutexStruct->mutex.time_start, currentTime)) + { + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isWaiting = false; + OSA_EnableIRQGlobal(); + return osaStatus_Timeout; + } + } + else if (millisec != osaWaitForever_c) /* If dont't wait forever, start timer. */ + { + /* Start the timeout counter */ + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isWaiting = true; + OSA_EnableIRQGlobal(); + pMutexStruct->mutex.time_start = OSA_TimeGetMsec(); + pMutexStruct->mutex.timeout = millisec; + } +#endif + } + + return osaStatus_Idle; +#else + mutexId=mutexId; + millisec=millisec; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexUnlock + * Description : This function is used to unlock a mutex. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + osMutexStruct_t* pMutexStruct; + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + pMutexStruct = (osMutexStruct_t*)mutexId; + OSA_DisableIRQGlobal(); + pMutexStruct->mutex.isLocked = false; + OSA_EnableIRQGlobal(); + return osaStatus_Success; +#else + mutexId=mutexId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexDestroy + * Description : This function is used to destroy a mutex. + * Return : osaStatus_Success if the lock object is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + if(osObjectIsAllocated(&osMutexInfo, mutexId) == FALSE) + { + return osaStatus_Error; + } + OSA_InterruptDisable(); + osObjectFree(&osMutexInfo, mutexId); + OSA_InterruptEnable(); + + return osaStatus_Success; +#else + mutexId=mutexId; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventCreate + * Description : This function is used to create a event object. + * Return : Event handle of the new event, or NULL if failed. + * + *END**************************************************************************/ +osaEventId_t OSA_EventCreate(bool_t autoClear) +{ +#if osNumberOfEvents + osaEventId_t eventId; + osEventStruct_t* pEventStruct; + OSA_InterruptDisable(); + eventId = pEventStruct = osObjectAlloc(&osEventInfo); + OSA_InterruptEnable(); + if(eventId == NULL) + { + return NULL; + } + pEventStruct->event.isWaiting = false; + pEventStruct->event.flags = 0; + pEventStruct->event.autoClear = autoClear; + pEventStruct->event.time_start = 0u; + pEventStruct->event.timeout = 0u; + pEventStruct->event.waitingTask = NULL; + return eventId; +#else + (void)autoClear; + return NULL; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventSet + * Description : Set one or more event flags of an event object. + * Return : osaStatus_Success if set successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + /* Set flags ensuring atomic operation */ + OSA_DisableIRQGlobal(); + pEventStruct->event.flags |= flagsToSet; + if (pEventStruct->event.waitingTask != NULL) + { + pEventStruct->event.waitingTask->haveToRun = true; + } + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToSet; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventClear + * Description : Clear one or more event flags of an event object. + * Return :osaStatus_Success if clear successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + /* Clear flags ensuring atomic operation */ + OSA_DisableIRQGlobal(); + pEventStruct->event.flags &= ~flagsToClear; + if (pEventStruct->event.flags != 0x00) + { + if (pEventStruct->event.waitingTask != NULL) + { + pEventStruct->event.waitingTask->haveToRun = true; + } + } + OSA_EnableIRQGlobal(); + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToClear; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventWait + * Description : This function checks the event's status, if it meets the wait + * condition, return osaStatus_Success, otherwise, timeout will be used for + * wait. The parameter timeout indicates how long should wait in milliseconds. + * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value + * osaStatus_Timeout immediately if wait condition is not met. The event flags + * will be cleared if the event is auto clear mode. Flags that wakeup waiting + * task could be obtained from the parameter setFlags. + * This function returns osaStatus_Success if wait condition is met, returns + * osaStatus_Timeout if wait condition is not met within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + osaStatus_t retVal = osaStatus_Idle; + if(pSetFlags == NULL) + { + return osaStatus_Error; + } + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + + OSA_DisableIRQGlobal(); +#if (TASK_MAX_NUM > 0) + pEventStruct->event.waitingTask = OSA_TaskGetId(); +#endif + + *pSetFlags = pEventStruct->event.flags & flagsToWait; + + /* Check the event flag first, if does not meet wait condition, deal with timeout. */ + if ((((!waitAll) && (*pSetFlags))) || (*pSetFlags == flagsToWait)) + { + pEventStruct->event.isWaiting = false; + if(TRUE == pEventStruct->event.autoClear) + { + pEventStruct->event.flags &= ~flagsToWait; + pEventStruct->event.waitingTask->haveToRun = false; /* Cherry-picked from [MCKFW-1872] */ + } + retVal = osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */ + retVal = osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pEventStruct->event.isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pEventStruct->event.timeout < OSA_TimeDiff(pEventStruct->event.time_start, currentTime)) + { + pEventStruct->event.isWaiting = false; + retVal = osaStatus_Timeout; + } + } + else if(millisec != osaWaitForever_c) /* If no timeout, don't start the timer */ + { + /* Start the timeout counter */ + pEventStruct->event.isWaiting = true; + pEventStruct->event.time_start = OSA_TimeGetMsec(); + pEventStruct->event.timeout = millisec; + } +#endif + else + { + pEventStruct->event.waitingTask->haveToRun = false; + } + } + + OSA_EnableIRQGlobal(); + + return retVal; +#else + (void)eventId; + (void)flagsToWait; + (void)waitAll; + (void)millisec; + (void)pSetFlags; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventDestroy + * Description : This function is used to destroy a event object. Return + * osaStatus_Success if the event object is destroyed successfully, otherwise + * return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_EventDestroy(osaEventId_t eventId) +{ +#if osNumberOfEvents + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + (void)eventId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQCreate + * Description : This function is used to create a message queue. + * Return : the handle to the message queue if create successfully, otherwise + * return NULL. + * + *END**************************************************************************/ +osaMsgQId_t OSA_MsgQCreate(uint32_t msgNo) +{ +#if osNumberOfMessageQs + osaMsgQId_t msgQId = NULL; + osMsgQStruct_t* pMsgQStruct; + + if(msgNo <= osNumberOfMessages) + { + OSA_InterruptDisable(); + msgQId = pMsgQStruct = osObjectAlloc(&osMsgQInfo); + OSA_InterruptEnable(); + + if(msgQId) + { + pMsgQStruct->queue.max = msgNo; + pMsgQStruct->queue.number = 0; + pMsgQStruct->queue.head = 0; + pMsgQStruct->queue.tail = 0; + } + } + + return msgQId; +#else + msgNo=msgNo; + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQPut + * Description : This function is used to put a message to a message queue. +* Return : osaStatus_Success if the message is put successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, void* pMessage) +{ +#if osNumberOfMessageQs + msg_queue_t* pQueue; + osaStatus_t status = osaStatus_Success; + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + + OSA_DisableIRQGlobal(); + if( pQueue->number >= pQueue->max ) + { + status = osaStatus_Error; + } + else + { + pQueue->queueMem[pQueue->tail] = *((uint32_t*)pMessage); + pQueue->number++; + pQueue->tail++; + + if( pQueue->tail >= pQueue->max ) + { + pQueue->tail = 0; + } + + if( pQueue->waitingTask ) + { + pQueue->waitingTask->haveToRun = 1; + } + } + OSA_EnableIRQGlobal(); + } + + return status; +#else + msgQId=msgQId; + pMessage=pMessage; + return osaStatus_Error; +#endif +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQGet + * Description : This function checks the queue's status, if it is not empty, + * get message from it and return osaStatus_Success, otherwise, timeout will + * be used for wait. The parameter timeout indicates how long should wait in + * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return + * osaStatus_Timeout immediately if queue is empty. + * This function returns osaStatus_Success if message is got successfully, + * returns osaStatus_Timeout if message queue is empty within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, void *pMessage, uint32_t millisec) +{ +#if osNumberOfMessageQs + osaStatus_t status = osaStatus_Idle; + msg_queue_t* pQueue; +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + uint32_t currentTime; +#endif + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + pQueue->waitingTask = OSA_TaskGetId(); + + OSA_DisableIRQGlobal(); + if( pQueue->number ) + { + *((uint32_t*)pMessage) = pQueue->queueMem[pQueue->head]; + pQueue->number--; + pQueue->head++; + pQueue->isWaiting = 0; + + if( pQueue->head >= pQueue->max ) + { + pQueue->head = 0; + } + status = osaStatus_Success; + } + else + { + if (0 == millisec) + { + /* If timeout is 0 and wait condition is not met, return kStatus_OSA_Timeout. */ + status = osaStatus_Timeout; + } +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) + else if (pQueue->isWaiting) + { + /* Check for timeout */ + currentTime = OSA_TimeGetMsec(); + if (pQueue->timeout < OSA_TimeDiff(pQueue->time_start, currentTime)) + { + pQueue->isWaiting = 0; + status = osaStatus_Timeout; + } + } + else if(millisec != osaWaitForever_c) /* If no timeout, don't start the timer */ + { + /* Start the timeout counter */ + pQueue->isWaiting = 1; + pQueue->time_start = OSA_TimeGetMsec(); + pQueue->timeout = millisec; + } +#endif + else + { + pQueue->waitingTask->haveToRun = 0; + } + } + OSA_EnableIRQGlobal(); + } + + return status; +#else + msgQId=msgQId; + pMessage=pMessage; + millisec=millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EXT_MsgQDestroy + * Description : This function is used to destroy the message queue. + * Return : osaStatus_Success if the message queue is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId) +{ +#if osNumberOfMessageQs + osaStatus_t status = osaStatus_Success; + msg_queue_t* pQueue; + + if(osObjectIsAllocated(&osMsgQInfo, msgQId) == FALSE) + { + status = osaStatus_Error; + } + else + { + pQueue = &((osMsgQStruct_t*)msgQId)->queue; + + if( pQueue->waitingTask ) + { + pQueue->waitingTask->haveToRun = 1; + pQueue->waitingTask = NULL; + } + + OSA_InterruptDisable(); + osObjectFree(&osMsgQInfo, msgQId); + OSA_InterruptEnable(); + } + + return status; +#else + msgQId=msgQId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptEnable(void) +{ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptDisable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptDisable(void) +{ + OSA_DisableIRQGlobal(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestricted + * Description : Disable interrupts except high-priority ones + * + *END**************************************************************************/ + void OSA_InterruptEnableRestricted(uint32_t *pu32OldIntLevel) +{ + /* Disable interrupts for duration of this function */ + OSA_DisableIRQGlobal(); + + /* Store old priority level */ + *pu32OldIntLevel = __get_BASEPRI(); + + /* Update priority level, but only if it is a more restrictive value */ + __set_BASEPRI_MAX(((3U << (8U - __NVIC_PRIO_BITS)) & 0xffU)); + + /* Restore interrupts */ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestore + * Description : Restore interrupts that were previously restricted by a call + * to OSA_InterruptEnableRestricted + * + *END**************************************************************************/ + void OSA_InterruptEnableRestore(uint32_t *pu32OldIntLevel) +{ + // write value direct into register ARM to ARM, no translations required + __set_BASEPRI(*pu32OldIntLevel); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InstallIntHandler + * Description : This function is used to install interrupt handler. + * + *END**************************************************************************/ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)) +{ +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_suppress = Pm138") +#endif +#ifdef ENABLE_RAM_VECTOR_TABLE + InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t)handler); +#endif +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_remark = PM138") +#endif +} + +/*! ********************************************************************************* +************************************************************************************* +* Private functions +************************************************************************************* +********************************************************************************** */ +#if (osCustomStartup == 0) +OSA_TASK_DEFINE(main_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0); + +int main (void) +{ + extern void hardware_init(void); + + OSA_Init(); + /* Initialize MCU clock */ + hardware_init(); + OSA_TimeInit(); + OSA_TaskCreate(OSA_TASK(main_task),NULL); + OSA_Start(); + + return 0; +} +#endif + +/*! ********************************************************************************* +* \brief Allocates a osObjectStruct_t block in the osObjectHeap array. +* \param[in] pointer to the object info struct. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return Pointer to the allocated osObjectStruct_t, NULL if failed. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++) + { + if(((osObjStruct_t*)pObj)->inUse == 0) + { + ((osObjStruct_t*)pObj)->inUse = 1; + return (void*)pObj; + } + + pObj += pOsObjectInfo->objectStructSize; + } + return NULL; +} +#endif +/*! ********************************************************************************* +* \brief Verifies the object is valid and allocated in the osObjectHeap array. +* \param[in] the pointer to the object info struct. +* \param[in] the pointer to the object struct. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return TRUE if the object is valid and allocated, FALSE otherwise +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++) + { + if(pObj == pObjectStruct) + { + if(((osObjStruct_t*)pObj)->inUse) + { + return TRUE; + } + break; + } + pObj += pOsObjectInfo->objectStructSize; + } + return FALSE; +} +#endif + +/*! ********************************************************************************* +* \brief Frees an osObjectStruct_t block from the osObjectHeap array. +* \param[in] pointer to the object info struct. +* \param[in] Pointer to the allocated osObjectStruct_t to free. +* Object can be semaphore, mutex, osTimer, message Queue, event +* \return none. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0; i < pOsObjectInfo->objNo; i++ ) + { + if(pObj == pObjectStruct) + { + ((osObjStruct_t*)pObj)->inUse = 0; + break; + } + + pObj += pOsObjectInfo->objectStructSize; + } +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_Init + * Description : This function is used to setup the basic services, it should + * be called first in function main. Return kStatus_OSA_Success if services + * are initialized successfully, otherwise return kStatus_OSA_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_Init(void) +{ +#if (TASK_MAX_NUM > 0) + task_init(); +#endif + + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_Start + * Description : This function is used to start RTOS scheduler. + * + *END**************************************************************************/ +void OSA_Start(void) +{ +#if (TASK_MAX_NUM > 0) + g_curTask = p_taskListHead; + + for(;;) + { + if(g_curTask->haveToRun) + { + if(g_curTask->p_func) + { + g_curTask->p_func(g_curTask->param); + } + /* restart from the first task */ + g_curTask = p_taskListHead; + } + else + { + g_curTask = g_curTask->next; + } + } +#else + for(;;) + { + } +#endif +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InsertTaskBefore + * Description : Helper function to insert Task TCB into the task list. + * + *END**************************************************************************/ +static void OSA_InsertTaskBefore(task_handler_t newTCB, task_handler_t currentTCB) +{ + newTCB->next = currentTCB; + newTCB->prev = currentTCB->prev; + currentTCB->prev->next = newTCB; + currentTCB->prev = newTCB; +} + + +/*FUNCTION********************************************************************** + * + * Function Name : SysTick_Handler + * Description : This ISR of the SYSTICK timer. + * + *END**************************************************************************/ +#if (FSL_OSA_BM_TIMER_CONFIG != FSL_OSA_BM_TIMER_NONE) +void SysTick_Handler(void) +{ + gTickCounter++; +} +#endif diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c new file mode 100755 index 000000000..906c61e9e --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/OSAbstraction/Source/fsl_os_abstraction_free_rtos.c @@ -0,0 +1,1173 @@ +/*! ********************************************************************************* +* Copyright (c) 2015, Freescale Semiconductor, Inc. +* Copyright 2016-2017, 2019 NXP +* All rights reserved. +* +* \file +* +* This is the source file for the OS Abstraction layer for freertos. +* +* SPDX-License-Identifier: BSD-3-Clause +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ +#include "EmbeddedTypes.h" +#include "fsl_os_abstraction.h" +#include "fsl_os_abstraction_free_rtos.h" +#include +#include "GenericList.h" +#include "fsl_common.h" +#include "Panic.h" +/*! ********************************************************************************* +************************************************************************************* +* Private macros +************************************************************************************* +********************************************************************************** */ +#define millisecToTicks(millisec) ((millisec * configTICK_RATE_HZ + 999)/1000) + +#ifdef DEBUG_ASSERT +#define OS_ASSERT(condition) if(!(condition))while(1); +#else +#define OS_ASSERT(condition) (void)(condition); +#endif + +#if (osNumberOfEvents) +#define osObjectAlloc_c 1 +#else +#define osObjectAlloc_c 0 +#endif + +/*! @brief Converts milliseconds to ticks*/ +#define MSEC_TO_TICK(msec) (((uint32_t)(msec)+500uL/(uint32_t)configTICK_RATE_HZ) \ + *(uint32_t)configTICK_RATE_HZ/1000uL) +#define TICKS_TO_MSEC(tick) ((uint64_t)(tick)*1000uL/(uint32_t)configTICK_RATE_HZ) +/************************************************************************************ +************************************************************************************* +* Private type definitions +************************************************************************************* +************************************************************************************/ + +typedef struct osEventStruct_tag +{ + uint32_t inUse; + event_t event; +}osEventStruct_t; + +typedef struct osObjStruct_tag +{ + uint32_t inUse; + uint32_t osObj; +}osObjStruct_t; + +typedef struct osObjectInfo_tag +{ + void* pHeap; + uint32_t objectStructSize; + uint32_t objNo; +} osObjectInfo_t; + + +/*! ********************************************************************************* +************************************************************************************* +* Private prototypes +************************************************************************************* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo); +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct); +#endif +extern void main_task(void const *argument); +extern void hardware_init(void); +void startup_task(void* argument); + + +/*! ********************************************************************************* +************************************************************************************* +* Public memory declarations +************************************************************************************* +********************************************************************************** */ +const uint8_t gUseRtos_c = USE_RTOS; // USE_RTOS = 0 for BareMetal and 1 for OS +static uint32_t g_base_priority_array[OSA_MAX_ISR_CRITICAL_SECTION_DEPTH]; +static int32_t g_base_priority_top = 0; + +/*! ********************************************************************************* +************************************************************************************* +* Private memory declarations +************************************************************************************* +********************************************************************************** */ + +#if osNumberOfEvents +osEventStruct_t osEventHeap[osNumberOfEvents]; +const osObjectInfo_t osEventInfo = {osEventHeap, sizeof(osEventStruct_t),osNumberOfEvents}; +#endif + + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ + +/*FUNCTION********************************************************************** + * + * Function Name : startup_task + * Description : Wrapper over main_task.. + * + *END**************************************************************************/ +void startup_task(void* argument) +{ + main_task(argument); + while(1); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetId + * Description : This function is used to get current active task's handler. + * + *END**************************************************************************/ +osaTaskId_t OSA_TaskGetId(void) +{ + return xTaskGetCurrentTaskHandle(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskYield + * Description : When a task calls this function, it will give up CPU and put + * itself to the tail of ready list. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskYield(void) +{ + taskYIELD(); + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetPriority + * Description : This function returns task's priority by task handler. + * + *END**************************************************************************/ +osaTaskPriority_t OSA_TaskGetPriority(osaTaskId_t taskId) +{ + return (osaTaskPriority_t)(PRIORITY_RTOS_TO_OSA(uxTaskPriorityGet((task_handler_t)taskId))); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskSetPriority + * Description : This function sets task's priority by task handler. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskSetPriority(osaTaskId_t taskId, osaTaskPriority_t taskPriority) +{ + vTaskPrioritySet((task_handler_t)taskId, PRIORITY_OSA_TO_RTOS(taskPriority)); + return osaStatus_Success; +} + +/*FUNCTION********************************************************************** +* +* Function Name : OSA_TaskCreate +* Description : This function is used to create a task and make it ready. +* Param[in] : threadDef - Definition of the thread. +* task_param - Parameter to pass to the new thread. +* Return Thread handle of the new thread, or NULL if failed. +* +*END**************************************************************************/ +osaTaskId_t OSA_TaskCreate(osaThreadDef_t *thread_def,osaTaskParam_t task_param) +{ + osaTaskId_t taskId = NULL; + task_handler_t task_handler; + + if (xTaskCreate( + (task_t)thread_def->pthread, /* pointer to the task */ + (char const*)thread_def->tname, /* task name for kernel awareness debugging */ + thread_def->stacksize/sizeof(portSTACK_TYPE), /* task stack size */ + (task_param_t)task_param, /* optional task startup argument */ + PRIORITY_OSA_TO_RTOS(thread_def->tpriority), /* initial priority */ + &task_handler /* optional task handle to create */ + ) == pdPASS) + { + taskId = (osaTaskId_t)task_handler; + } + return taskId; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskDestroy + * Description : This function destroy a task. + * Param[in] :taskId - Thread handle. + * Return osaStatus_Success if the task is destroied, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_TaskDestroy(osaTaskId_t taskId) +{ + osaStatus_t status; + uint16_t oldPriority; + /*Change priority to avoid context switches*/ + oldPriority = OSA_TaskGetPriority(OSA_TaskGetId()); + (void)OSA_TaskSetPriority(OSA_TaskGetId(), OSA_PRIORITY_REAL_TIME); +#if INCLUDE_vTaskDelete /* vTaskDelete() enabled */ + vTaskDelete((task_handler_t)taskId); + status = osaStatus_Success; +#else + status = osaStatus_Error; /* vTaskDelete() not available */ +#endif + (void)OSA_TaskSetPriority(OSA_TaskGetId(), oldPriority); + + return status; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeDelay + * Description : This function is used to suspend the active thread for the given number of milliseconds. + * + *END**************************************************************************/ +void OSA_TimeDelay(uint32_t millisec) +{ + vTaskDelay(millisecToTicks(millisec)); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeGetMsec + * Description : This function gets current time in milliseconds. + * + *END**************************************************************************/ +uint32_t OSA_TimeGetMsec(void) +{ + portTickType ticks; + + if (__get_IPSR()) + { + ticks = xTaskGetTickCountFromISR(); + } + else + { + ticks = xTaskGetTickCount(); + } + + return TICKS_TO_MSEC(ticks); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreCreate + * Description : This function is used to create a semaphore. + * Return : Semaphore handle of the new semaphore, or NULL if failed. + * + *END**************************************************************************/ +osaSemaphoreId_t OSA_SemaphoreCreate(uint32_t initValue) +{ +#if osNumberOfSemaphores + semaphore_t sem; + sem = xSemaphoreCreateCounting(0xFF, initValue); + return (osaSemaphoreId_t)sem; +#else + (void)initValue; + return NULL; +#endif + +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreDestroy + * Description : This function is used to destroy a semaphore. + * Return : osaStatus_Success if the semaphore is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreDestroy(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + semaphore_t sem = (semaphore_t)semId; + if(sem == NULL) + { + return osaStatus_Error; + } + vSemaphoreDelete(sem); + return osaStatus_Success; +#else + (void)semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreWait + * Description : This function checks the semaphore's counting value, if it is + * positive, decreases it and returns osaStatus_Success, otherwise, timeout + * will be used for wait. The parameter timeout indicates how long should wait + * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will + * return osaStatus_Timeout immediately if semaphore is not positive. + * This function returns osaStatus_Success if the semaphore is received, returns + * osaStatus_Timeout if the semaphore is not received within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphoreWait(osaSemaphoreId_t semId, uint32_t millisec) +{ +#if osNumberOfSemaphores + uint32_t timeoutTicks; + if(semId == NULL) + { + return osaStatus_Error; + } + semaphore_t sem = (semaphore_t)semId; + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + + if (xSemaphoreTake(sem, timeoutTicks)==pdFALSE) + { + return osaStatus_Timeout; /* timeout */ + } + else + { + return osaStatus_Success; /* semaphore taken */ + } +#else + (void)semId; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphorePost + * Description : This function is used to wake up one task that wating on the + * semaphore. If no task is waiting, increase the semaphore. The function returns + * osaStatus_Success if the semaphre is post successfully, otherwise returns + * osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_SemaphorePost(osaSemaphoreId_t semId) +{ +#if osNumberOfSemaphores + osaStatus_t status = osaStatus_Error; + if(semId) + { + semaphore_t sem = (semaphore_t)semId; + + if (__get_IPSR()) + { + portBASE_TYPE taskToWake = pdFALSE; + + if (pdTRUE==xSemaphoreGiveFromISR(sem, &taskToWake)) + { + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + status = osaStatus_Success; + } + else + { + status = osaStatus_Error; + } + } + else + { + if (pdTRUE == xSemaphoreGive(sem)) + { + status = osaStatus_Success; /* sync object given */ + } + else + { + status = osaStatus_Error; + } + } + } + return status; +#else + (void)semId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexCreate + * Description : This function is used to create a mutex. + * Return : Mutex handle of the new mutex, or NULL if failed. + * + *END**************************************************************************/ +osaMutexId_t OSA_MutexCreate(void) +{ +#if osNumberOfMutexes + mutex_t mutex; + mutex = xSemaphoreCreateMutex(); + return (osaMutexId_t)mutex; +#else + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexLock + * Description : This function checks the mutex's status, if it is unlocked, + * lock it and returns osaStatus_Success, otherwise, wait for the mutex. + * This function returns osaStatus_Success if the mutex is obtained, returns + * osaStatus_Error if any errors occur during waiting. If the mutex has been + * locked, pass 0 as timeout will return osaStatus_Timeout immediately. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) +{ +#if osNumberOfMutexes + uint32_t timeoutTicks; + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + /* If pMutex has been locked by current task, return error. */ + if (xSemaphoreGetMutexHolder(mutex) == xTaskGetCurrentTaskHandle()) + { + return osaStatus_Error; + } + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + + if (xSemaphoreTake(mutex, timeoutTicks)==pdFALSE) + { + return osaStatus_Timeout; /* timeout */ + } + else + { + return osaStatus_Success; /* semaphore taken */ + } +#else + (void)mutexId; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexUnlock + * Description : This function is used to unlock a mutex. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + /* If pMutex is not locked by current task, return error. */ + if (xSemaphoreGetMutexHolder(mutex) != xTaskGetCurrentTaskHandle()) + { + return osaStatus_Error; + } + + if (xSemaphoreGive(mutex)==pdPASS) + { + return osaStatus_Success; + } + else + { + return osaStatus_Error; + } +#else + (void)mutexId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexDestroy + * Description : This function is used to destroy a mutex. + * Return : osaStatus_Success if the lock object is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MutexDestroy(osaMutexId_t mutexId) +{ +#if osNumberOfMutexes + mutex_t mutex = (mutex_t)mutexId; + if(mutexId == NULL) + { + return osaStatus_Error; + } + vSemaphoreDelete(mutex); + return osaStatus_Success; +#else + (void)mutexId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventCreate + * Description : This function is used to create a event object. + * Return : Event handle of the new event, or NULL if failed. + * + *END**************************************************************************/ +osaEventId_t OSA_EventCreate(bool_t autoClear) +{ +#if osNumberOfEvents + osaEventId_t eventId; + osEventStruct_t* pEventStruct; + OSA_InterruptDisable(); + eventId = pEventStruct = osObjectAlloc(&osEventInfo); + OSA_InterruptEnable(); + if(eventId == NULL) + { + return NULL; + } + + pEventStruct->event.eventHandler = xEventGroupCreate(); + if (pEventStruct->event.eventHandler) + { + pEventStruct->event.autoClear = autoClear; + } + else + { + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + eventId = NULL; + } + return eventId; +#else + (void)autoClear; + return NULL; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventSet + * Description : Set one or more event flags of an event object. + * Return : osaStatus_Success if set successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventSet(osaEventId_t eventId, osaEventFlags_t flagsToSet) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + portBASE_TYPE taskToWake = pdFALSE; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + if (__get_IPSR()) + { + if (pdPASS != xEventGroupSetBitsFromISR(pEventStruct->event.eventHandler, (event_flags_t)flagsToSet, &taskToWake)) + { + panic(0,(uint32_t)OSA_EventSet,0,0); + return osaStatus_Error; + } + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + } + else + { + xEventGroupSetBits(pEventStruct->event.eventHandler, (event_flags_t)flagsToSet); + } + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToSet; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventClear + * Description : Clear one or more event flags of an event object. + * Return :osaStatus_Success if clear successfully, osaStatus_Error if failed. + * + *END**************************************************************************/ +osaStatus_t OSA_EventClear(osaEventId_t eventId, osaEventFlags_t flagsToClear) +{ +#if osNumberOfEvents + + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + + if (__get_IPSR()) + { + xEventGroupClearBitsFromISR(pEventStruct->event.eventHandler, (event_flags_t)flagsToClear); + } + else + { + xEventGroupClearBits(pEventStruct->event.eventHandler, (event_flags_t)flagsToClear); + } + + return osaStatus_Success; +#else + (void)eventId; + (void)flagsToClear; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventWait + * Description : This function checks the event's status, if it meets the wait + * condition, return osaStatus_Success, otherwise, timeout will be used for + * wait. The parameter timeout indicates how long should wait in milliseconds. + * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value + * osaStatus_Timeout immediately if wait condition is not met. The event flags + * will be cleared if the event is auto clear mode. Flags that wakeup waiting + * task could be obtained from the parameter setFlags. + * This function returns osaStatus_Success if wait condition is met, returns + * osaStatus_Timeout if wait condition is not met within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_EventWait(osaEventId_t eventId, osaEventFlags_t flagsToWait, bool_t waitAll, uint32_t millisec, osaEventFlags_t *pSetFlags) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + BaseType_t clearMode; + uint32_t timeoutTicks; + event_flags_t flagsSave; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + + /* Clean FreeRTOS cotrol flags */ + flagsToWait = flagsToWait & 0x00FFFFFF; + + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = millisec/portTICK_PERIOD_MS; + } + + clearMode = (pEventStruct->event.autoClear) ? pdTRUE: pdFALSE; + + flagsSave = xEventGroupWaitBits(pEventStruct->event.eventHandler,(event_flags_t)flagsToWait,clearMode,(BaseType_t)waitAll,timeoutTicks); + + flagsSave &= (event_flags_t)flagsToWait; + if(pSetFlags) + { + *pSetFlags = (osaEventFlags_t)flagsSave; + } + + if (flagsSave) + { + return osaStatus_Success; + } + else + { + return osaStatus_Timeout; + } +#else + (void)eventId; + (void)flagsToWait; + (void)waitAll; + (void)millisec; + (void)pSetFlags; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventDestroy + * Description : This function is used to destroy a event object. Return + * osaStatus_Success if the event object is destroyed successfully, otherwise + * return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_EventDestroy(osaEventId_t eventId) +{ +#if osNumberOfEvents + osEventStruct_t* pEventStruct; + if(osObjectIsAllocated(&osEventInfo, eventId) == FALSE) + { + return osaStatus_Error; + } + pEventStruct = (osEventStruct_t*)eventId; + if(pEventStruct->event.eventHandler == NULL) + { + return osaStatus_Error; + } + vEventGroupDelete(pEventStruct->event.eventHandler); + OSA_InterruptDisable(); + osObjectFree(&osEventInfo, eventId); + OSA_InterruptEnable(); + return osaStatus_Success; +#else + (void)eventId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQCreate + * Description : This function is used to create a message queue. + * Return : the handle to the message queue if create successfully, otherwise + * return NULL. + * + *END**************************************************************************/ +osaMsgQId_t OSA_MsgQCreate( uint32_t msgNo ) +{ +#if osNumberOfMessageQs + msg_queue_handler_t msg_queue_handler; + + /* Create the message queue where each element is a pointer to the message item. */ + msg_queue_handler = xQueueCreate(msgNo,sizeof(osaMsg_t)); + return (osaMsgQId_t)msg_queue_handler; +#else + (void)msgNo; + return NULL; +#endif +} + + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQPut + * Description : This function is used to put a message to a message queue. +* Return : osaStatus_Success if the message is put successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQPut(osaMsgQId_t msgQId, void* pMessage) +{ +#if osNumberOfMessageQs + msg_queue_handler_t handler; + osaStatus_t osaStatus; + if(msgQId == NULL) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + { + if (__get_IPSR()) + { + portBASE_TYPE taskToWake = pdFALSE; + + if (pdTRUE == xQueueSendToBackFromISR(handler, pMessage, &taskToWake)) + { + if (pdTRUE == taskToWake) + { + portYIELD_FROM_ISR(taskToWake); + } + osaStatus = osaStatus_Success; + } + else + { + osaStatus = osaStatus_Error; + } + + } + else + { + osaStatus = (xQueueSendToBack(handler, pMessage, 0)== pdPASS)?(osaStatus_Success):(osaStatus_Error); + } + } + return osaStatus; +#else + (void)msgQId; + (void)pMessage; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQGet + * Description : This function checks the queue's status, if it is not empty, + * get message from it and return osaStatus_Success, otherwise, timeout will + * be used for wait. The parameter timeout indicates how long should wait in + * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return + * osaStatus_Timeout immediately if queue is empty. + * This function returns osaStatus_Success if message is got successfully, + * returns osaStatus_Timeout if message queue is empty within the specified + * 'timeout', returns osaStatus_Error if any errors occur during waiting. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQGet(osaMsgQId_t msgQId, void *pMessage, uint32_t millisec) +{ +#if osNumberOfMessageQs + osaStatus_t osaStatus; + msg_queue_handler_t handler; + uint32_t timeoutTicks; + if( msgQId == NULL ) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + if (millisec == osaWaitForever_c) + { + timeoutTicks = portMAX_DELAY; + } + else + { + timeoutTicks = MSEC_TO_TICK(millisec); + } + if (xQueueReceive(handler, pMessage, timeoutTicks)!=pdPASS) + { + osaStatus = osaStatus_Timeout; /* not able to send it to the queue? */ + } + else + { + osaStatus = osaStatus_Success; + } + return osaStatus; +#else + (void)msgQId; + (void)pMessage; + (void)millisec; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQDestroy + * Description : This function is used to destroy the message queue. + * Return : osaStatus_Success if the message queue is destroyed successfully, otherwise return osaStatus_Error. + * + *END**************************************************************************/ +osaStatus_t OSA_MsgQDestroy(osaMsgQId_t msgQId) +{ +#if osNumberOfMessageQs + msg_queue_handler_t handler; + if(msgQId == NULL ) + { + return osaStatus_Error; + } + handler = (msg_queue_handler_t)msgQId; + vQueueDelete(handler); + return osaStatus_Success; +#else + (void)msgQId; + return osaStatus_Error; +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptEnable(void) +{ + if (__get_IPSR()) + { + if(g_base_priority_top) + { + g_base_priority_top--; + portCLEAR_INTERRUPT_MASK_FROM_ISR(g_base_priority_array[g_base_priority_top]); + } + + } + else + { + portEXIT_CRITICAL(); + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptDisable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptDisable(void) +{ + if (__get_IPSR()) + { + if(g_base_priority_top < OSA_MAX_ISR_CRITICAL_SECTION_DEPTH) + { + g_base_priority_array[g_base_priority_top] = portSET_INTERRUPT_MASK_FROM_ISR(); + g_base_priority_top++; + } + + } + else + { + portENTER_CRITICAL(); + } + +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestricted + * Description : Disable interrupts except high-priority ones + * + *END**************************************************************************/ +void OSA_InterruptEnableRestricted(uint32_t *pu8OldIntLevel) +{ + /* Disable interrupts for duration of this function */ + OSA_DisableIRQGlobal(); + + /* Store old priority level */ + *pu8OldIntLevel = __get_BASEPRI(); + + /* Update priority level, but only if it is a more restrictive value */ + __set_BASEPRI_MAX((3U << (8U - __NVIC_PRIO_BITS)) & 0xffU); + + /* Restore interrupts */ + OSA_EnableIRQGlobal(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnableRestore + * Description : Restore interrupts that were previously restricted by a call + * to OSA_InterruptEnableRestricted + * + *END**************************************************************************/ +void OSA_InterruptEnableRestore(uint32_t *pu8OldIntLevel) +{ + // write value direct into register ARM to ARM, no translations required + __set_BASEPRI(*pu8OldIntLevel); +} + + +uint32_t gInterruptDisableCount = 0; +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EnableIRQGlobal + * Description : enable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_EnableIRQGlobal(void) +{ + if (gInterruptDisableCount > 0) + { + gInterruptDisableCount--; + + if (gInterruptDisableCount == 0) + { + __enable_irq(); + } + /* call core API to enable the global interrupt*/ + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_DisableIRQGlobal + * Description : disable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_DisableIRQGlobal(void) +{ + /* call core API to disable the global interrupt*/ + __disable_irq(); + + /* update counter*/ + gInterruptDisableCount++; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InstallIntHandler + * Description : This function is used to install interrupt handler. + * + *END**************************************************************************/ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)) +{ + +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_suppress = Pm138") +#endif + InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t)handler); +#if defined ( __IAR_SYSTEMS_ICC__ ) + _Pragma ("diag_remark = PM138") +#endif +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeInit + * Description : Empty + * + *END**************************************************************************/ +void OSA_TimeInit(void) +{ + +} + +/*! ********************************************************************************* +************************************************************************************* +* Private functions +************************************************************************************* +********************************************************************************** */ +OSA_TASK_DEFINE(startup_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0) ; +int main (void) +{ + /* Initialize MCU clock */ + hardware_init(); + OSA_TaskCreate(OSA_TASK(startup_task), NULL); + vTaskStartScheduler(); + + return 0; +} + +/*! ********************************************************************************* +* \brief Allocates a osObjectStruct_t block in the osObjectHeap array. +* \param[in] pointer to the object info struct. +* Object can be semaphore, mutex, message Queue, event +* \return Pointer to the allocated osObjectStruct_t, NULL if failed. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void* osObjectAlloc(const osObjectInfo_t* pOsObjectInfo) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++, pObj += pOsObjectInfo->objectStructSize) + { + if(((osObjStruct_t*)pObj)->inUse == 0) + { + ((osObjStruct_t*)pObj)->inUse = 1; + return (void*)pObj; + } + } + return NULL; +} +#endif + +/*! ********************************************************************************* +* \brief Verifies the object is valid and allocated in the osObjectHeap array. +* \param[in] the pointer to the object info struct. +* \param[in] the pointer to the object struct. +* Object can be semaphore, mutex, message Queue, event +* \return TRUE if the object is valid and allocated, FALSE otherwise +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static bool_t osObjectIsAllocated(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0 ; i < pOsObjectInfo->objNo ; i++ , pObj += pOsObjectInfo->objectStructSize) + { + if(pObj == pObjectStruct) + { + if(((osObjStruct_t*)pObj)->inUse) + { + return TRUE; + } + break; + } + } + return FALSE; +} +#endif + +/*! ********************************************************************************* +* \brief Frees an osObjectStruct_t block from the osObjectHeap array. +* \param[in] pointer to the object info struct. +* \param[in] Pointer to the allocated osObjectStruct_t to free. +* Object can be semaphore, mutex, message Queue, event +* \return none. +* +* \pre +* +* \post +* +* \remarks Function is unprotected from interrupts. +* +********************************************************************************** */ +#if osObjectAlloc_c +static void osObjectFree(const osObjectInfo_t* pOsObjectInfo, void* pObjectStruct) +{ + uint32_t i; + uint8_t* pObj = (uint8_t*)pOsObjectInfo->pHeap; + for( i=0; i < pOsObjectInfo->objNo; i++, pObj += pOsObjectInfo->objectStructSize ) + { + if(pObj == pObjectStruct) + { + ((osObjStruct_t*)pObj)->inUse = 0; + break; + } + } +} +#endif + +/*! ********************************************************************************* +* \brief FreeRTOS application malloc failed hook +* +* +* \remarks Function is called by FreeRTOS if there is not enough space in the +* heap for task stack allocation or for OS object allocation +* +********************************************************************************** */ +#if (configUSE_MALLOC_FAILED_HOOK==1) +void vApplicationMallocFailedHook (void) +{ + panic(0,(uint32_t)vApplicationMallocFailedHook,0,0); +} +#endif + diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Include/PDM.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Include/PDM.h new file mode 100755 index 000000000..a1650ab86 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Include/PDM.h @@ -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 ***/ +/****************************************************************************/ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Library/libPDM.a b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Library/libPDM.a new file mode 100755 index 000000000..9c40aac91 Binary files /dev/null and b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/Library/libPDM.a differ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/PDM.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/PDM.h new file mode 100755 index 000000000..a2b8f1001 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/PDM.h @@ -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 ***/ +/****************************************************************************/ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/pdm_port.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/pdm_port.c new file mode 100755 index 000000000..770a93106 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/PDM/pdm_port.c @@ -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 +#include +#include + +#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; +} +/*-----------------------------------------------------------*/ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Interface/Panic.h b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Interface/Panic.h new file mode 100755 index 000000000..aa65ec716 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Interface/Panic.h @@ -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__ */ diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Source/Panic.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Source/Panic.c new file mode 100755 index 000000000..8315b0c1a --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Panic/Source/Panic.c @@ -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 diff --git a/third_party/nxp/K32W061DK6/middleware/wireless/framework/Reset/Reset.c b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Reset/Reset.c new file mode 100755 index 000000000..9fa25ce27 --- /dev/null +++ b/third_party/nxp/K32W061DK6/middleware/wireless/framework/Reset/Reset.c @@ -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 ***************************************/