From 96793a53df87d49383f6714673e48603c6c4b22a Mon Sep 17 00:00:00 2001 From: sundp Date: Sun, 15 Oct 2023 20:29:36 +0800 Subject: [PATCH] add hmac support --- Core/Inc/flash_if.h | 82 ++--- Core/Inc/sts_cmox_hmac_sha.h | 46 +++ Core/Inc/utilities_def.h | 1 + Core/Inc/yunhorn_sts_prd_conf.h | 18 +- Core/Inc/yunhorn_sts_sensors.h | 53 +++- Core/Src/cmox_low_level.c | 51 +++ Core/Src/flash_if.c | 542 ++++++++++++++++++++------------ Core/Src/sts_cmox_hmac_sha.c | 90 ++++++ LoRaWAN/App/lora_app.c | 264 +++++++++++----- 9 files changed, 828 insertions(+), 319 deletions(-) create mode 100644 Core/Inc/sts_cmox_hmac_sha.h create mode 100644 Core/Src/cmox_low_level.c create mode 100644 Core/Src/sts_cmox_hmac_sha.c diff --git a/Core/Inc/flash_if.h b/Core/Inc/flash_if.h index 74ac6a6..25e880b 100644 --- a/Core/Inc/flash_if.h +++ b/Core/Inc/flash_if.h @@ -35,18 +35,19 @@ extern "C" { /* Exported types ------------------------------------------------------------*/ /** - * @brief Flash status enumeration + * @brief Flash status */ -enum +typedef enum { - FLASH_PARAM_ERROR = -5, - FLASH_LOCK_ERROR = -4, - FLASH_WRITE_ERROR = -3, - FLASH_ERASE_ERROR = -2, - FLASH_ERROR = -1, - FLASH_OK = 0, - FLASH_BUSY = 1 -}; + FLASH_IF_PARAM_ERROR = -6, /*!< Error Flash invalid parameter */ + FLASH_IF_LOCK_ERROR = -5, /*!< Error Flash not locked */ + FLASH_IF_WRITE_ERROR = -4, /*!< Error Flash write not possible */ + FLASH_IF_READ_ERROR = -3, /*!< Error Flash read not possible */ + FLASH_IF_ERASE_ERROR = -2, /*!< Error Flash erase not possible */ + FLASH_IF_ERROR = -1, /*!< Error Flash generic */ + FLASH_IF_OK = 0, /*!< Flash Success */ + FLASH_IF_BUSY = 1 /*!< Flash not available */ +} FLASH_IF_StatusTypedef; /* USER CODE BEGIN ET */ @@ -63,51 +64,54 @@ enum /* USER CODE END EV */ /* Exported macro ------------------------------------------------------------*/ -#define PAGE(__ADDRESS__) (uint32_t)((((__ADDRESS__) - FLASH_BASE) % FLASH_BANK_SIZE) / FLASH_PAGE_SIZE) /*!< Get page index from page address */ - /* USER CODE BEGIN EM */ /* USER CODE END EM */ /* Exported functions prototypes ---------------------------------------------*/ /** - * @brief This function writes a user flash area (read/modify/write) - * @param address: ptr to user flash area - * @param data: ptr to data to be written - * @param size: number of 32b. - * @param dataTempPage: ptr used to copy already written page in ram - * @return Flash status. + * @brief This function initializes the internal and external flash interface + * + * @param pAllocRamBuffer pointer used to store a FLASH page in RAM when partial replacement is needed + * @return FLASH_IF_StatusTypedef status */ -int32_t FLASH_IF_Write(uint32_t address, uint8_t *data, uint32_t size, uint8_t *dataTempPage); +FLASH_IF_StatusTypedef FLASH_IF_Init(void *pAllocRamBuffer); /** - * Writes a 64-bit word in flash at a specific address. - * @param address (in bytes) must be a multiple of 8. - * @param data data to write - * @returns FLASH_OK, FLASH_BUSY, FLASH_ERASE_ERROR + * @brief This function de-initializes the internal and external flash interface + * + * @return FLASH_IF_StatusTypedef status */ -int32_t FLASH_IF_Write64(uint32_t address, uint64_t data); +FLASH_IF_StatusTypedef FLASH_IF_DeInit(void); /** - * Erases 'n' flash pages from page number 'page' to page number - * 'page + n - 1'. - * - If 'interrupt' is set to 0, the erasing is performed in polling mode. - * - If 'interrupt' is set to 1, the erasing is performed under FLASH - * interrupt: the function returns immediately and the user is informed of - * the end of erasing procedure by a call to the following function that - * must be implemented by the user: void HWCB_FLASH_EndOfCleanup( void ); - * this call-back function is called under FLASH IRQ handler. - * @param page memory start page number - * @param n number of page - * @param interrupt choice polling/interrupt - * @returns FLASH_OK, FLASH_BUSY, FLASH_ERASE_ERROR + * @brief This function writes a data buffer in internal or external flash + * + * @param pDestination pointer of flash address to write. It has to be 8 bytes aligned. + * @param pSource pointer on buffer with data to write + * @param uLength length of data buffer in bytes. It has to be 8 bytes aligned. + * @return FLASH_IF_StatusTypedef status */ -int32_t FLASH_IF_EraseByPages(uint32_t page, uint16_t n, int32_t interrupt); +FLASH_IF_StatusTypedef FLASH_IF_Write(void *pDestination, const void *pSource, uint32_t uLength); /** - * Callback + * @brief This function reads a amount of data from flash and copy into the output data buffer + * + * @param pDestination pointer of target location to copy the flash sector + * @param pSource pointer of flash address to read + * @param uLength number of bytes to read + * @return FLASH_IF_StatusTypedef status */ -void HWCB_FLASH_EndOfCleanup(void); +FLASH_IF_StatusTypedef FLASH_IF_Read(void *pDestination, const void *pSource, uint32_t uLength); + +/** + * @brief This function erases a amount of internal or external flash pages depending of the length + * + * @param pStart pointer of flash address to erase + * @param uLength number of bytes to erase + * @return FLASH_IF_StatusTypedef status + */ +FLASH_IF_StatusTypedef FLASH_IF_Erase(void *pStart, uint32_t uLength); /* USER CODE BEGIN EFP */ diff --git a/Core/Inc/sts_cmox_hmac_sha.h b/Core/Inc/sts_cmox_hmac_sha.h new file mode 100644 index 0000000..2c58ee7 --- /dev/null +++ b/Core/Inc/sts_cmox_hmac_sha.h @@ -0,0 +1,46 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : sts_cmox_hmac_sha.h * + * @author Yunhorn (r) Technology Limited Application Team * + * @brief Yunhorn (r) SmarToilets (r) HMAC-SHA1 Process file. * + * Description : Hash Message Authentication Code SHA * + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 Yunhorn Technology Limited. + * Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd. + * All rights reserved. + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. * + ****************************************************************************** + */ +/* USER CODE END Header */ + +#ifndef __sts_cmox_hmac_sha_h +#define __sts_cmox_hmac_sha_h + +#include +#include +#include +#include "cmox_crypto.h" + +typedef struct { + uint8_t hmac_tag[20]; + uint8_t hmac_tag_size; + uint8_t ac_pass; +} hmac_result_t; + +void STS_HMAC_TESTING(void); +uint32_t sts_hmac_sha1(const uint8_t *Key, int key_length, const uint8_t *Message, int message_length, hmac_result_t *hmac_result); +uint32_t sts_hmac_verify(void); + +#endif +/** + * @} + */ + +/** + * @} + */ diff --git a/Core/Inc/utilities_def.h b/Core/Inc/utilities_def.h index 9ec9baa..faf39d3 100644 --- a/Core/Inc/utilities_def.h +++ b/Core/Inc/utilities_def.h @@ -79,6 +79,7 @@ typedef enum CFG_SEQ_Task_LoRaStoreContextEvent, CFG_SEQ_Task_LoRaStopJoinEvent, /* USER CODE BEGIN CFG_SEQ_Task_Id_t */ + CFG_SEQ_Task_YunhornSTSEventRFAC, CFG_SEQ_Task_YunhornSTSEventP1, CFG_SEQ_Task_YunhornSTSEventP2, /* USER CODE END CFG_SEQ_Task_Id_t */ diff --git a/Core/Inc/yunhorn_sts_prd_conf.h b/Core/Inc/yunhorn_sts_prd_conf.h index 25b88ae..5c00f0f 100644 --- a/Core/Inc/yunhorn_sts_prd_conf.h +++ b/Core/Inc/yunhorn_sts_prd_conf.h @@ -62,9 +62,21 @@ #define MinorVer 10U #define SubMinorVer 15U #define FirmwareVersion 3U +/* #define YUNHORN_STS_M7_NVM_CFG_SIZE 3U #define YUNHORN_STS_M7_CFG_CMD_SIZE 9U #define YUNHORN_STS_MAX_NVM_CFG_SIZE 32U +*/ +#define STS_NVM_CFG_SIZE 32U +#define STS_CFG_PCFG_SIZE 28U +#define STS_CFG_CMD_SIZE 30U +#define STS_CFG_CMD_SHORT_LEN 8U +#define STS_MODE_COLOR_CMD_LEN 5U + +#define YUNHORN_STS_M7_NVM_CFG_SIZE 3U +#define YUNHORN_STS_M7_CFG_CMD_SIZE 9U +#define YUNHORN_STS_MAX_NVM_CFG_SIZE 64U +#define YUNHORN_STS_AC_CODE_SIZE 20U #include "yunhorn_sts_motion_sensor.h" #define YUNHORN_STS_M7_LORA_APP_DATA_PORT 20U @@ -141,9 +153,9 @@ * DEVICE TYPE On-chip Flash * Address range 0800 0000H - 0803 FFFFH Size: 0x0004 0000 */ - -#define FLASH_USER_START_ADDR ((uint32_t) 0x0803F800U) // Last 2kB of flash -#define FLASH_USER_CONFIG_SIZE ((uint32_t) 0x000007FFU) //0x400=1KB=1024 +#define STS_BURN_IN_RFAC ((uint32_t) 2) +#define FLASH_USER_START_ADDR ((void *) 0x0803F800U) // Last 2kB of flash +#define FLASH_USER_CONFIG_SIZE ((void *) 0x000007FFU) //0x400=1KB=1024 #define FLASH_USER_END_ADDR (FLASH_USER_START_ADDR + FLASH_USER_CONFIG - 1) /* 2KB = 2048 = 0x800 End @ of user Flash area */ diff --git a/Core/Inc/yunhorn_sts_sensors.h b/Core/Inc/yunhorn_sts_sensors.h index c0bf28f..e64b7dd 100644 --- a/Core/Inc/yunhorn_sts_sensors.h +++ b/Core/Inc/yunhorn_sts_sensors.h @@ -367,29 +367,59 @@ typedef struct /* Exported functions prototypes ---------------------------------------------*/ -enum { +enum nvm_order { NVM_MTM1=0, NVM_MTM2, NVM_VER, NVM_HWV, - NVM_PERIODICITY_H, - NVM_PERIODICITY_L, + NVM_PERIODICITY, NVM_UNIT, - NVM_LEN + NVM_SAMPLING, + NVM_S_UNIT, + NVM_WORK_MODE, + NVM_SERVICE_MASK, + NVM_RESERVE01, //10 + NVM_LEN, //11, 32=0x20 + NVM_CFG_START, //12, p[0] bytes for configs, + //13, p[1] + //14, p[2] + // ... + //39, P[27] + NVM_FALL_DETECTION_ACC_THRESHOLD=40, //40 + NVM_FALL_DETECTION_DEPTH_THRESHOLD, //41 + NVM_FALL_DETECTION_RESERVE, //42 + NVM_OCCUPANCY_OVERTIME_THRESHOLD, //43 + NVM_AC_CODE_START=44 //STORED, NO UPLOAD + //63, 20 bytes for AC code }; - typedef struct sts_cfg_nvm { uint8_t mtmcode1; uint8_t mtmcode2; uint8_t version; uint8_t hardware_ver; - uint8_t periodicity_h; //count of duty cycle duration high {0,9} - uint8_t periodicity_l; //count of duty cycle duration low {0,9} - uint8_t unit; // time unit of duty cycle duration, in 'S', 'M','H' seconds, minutes, hours - uint8_t length; - uint8_t p[YUNHORN_STS_MAX_NVM_CFG_SIZE-6]; + uint8_t periodicity; //count of uplink duty cycle duration high {99} + uint8_t unit; // uplink time unit of duty cycle duration, in 'S', 'M','H' seconds, minutes, hours + uint8_t sampling; // heart-beat interval or count of sampling duty cycle duration high {99} + uint8_t s_unit; // Heart-beat interval or sampling time unit of duty cycle duration, in 'S', 'M','H' seconds, minutes, hours + uint8_t work_mode; + uint8_t sts_service_mask; + uint8_t reseve01; + uint8_t length; // length of following parameters except AC CODE(20bytes) + uint8_t p[STS_CFG_PCFG_SIZE]; + uint8_t fall_detection_acc_threshold; // 0 - 9: 0:disable: 1-9 accelaration mg/s2 + uint8_t fall_detection_depth_threshold; // 0 - 9: 0:disable: 1-9 fall down depth * 10 cm + uint8_t fall_detection_reserve; + uint8_t occupancy_overtime_threshold; // 0 - 9£º 0£ºdisable, 1-9 occupy over time threshold * 10 min + uint8_t ac[YUNHORN_STS_AC_CODE_SIZE]; // authorization code, 20 bytes MCU UUID coded } sts_cfg_nvm_t; + +#define STS_SERVICE_MASK_L0 (0) // Service normal , no mask off +#define STS_SERVICE_MASK_L1 (1) // service mask level 1, sensing data upload in silence mode, node appearance silence (no LED, No display, no sound, no vibration) +#define STS_SERVICE_MASK_L2 (2) // service mask level 2, NO sensing data upload (event or periodicity) +#define STS_SERVICE_MASK_L3 (3) // service mask level 3, NO responsing to cloud control command, or config change/responding, EXCEPT STS_SERVICE_MASK_ON_OFF cmd + + /** * @brief Store/Write/Flash Configuration in RW RAM */ @@ -444,6 +474,9 @@ void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size); void STS_SENSOR_Function_Test_Process(void); +void STS_YunhornSTSEventRFAC_Process(void); +void STS_YunhornAuthenticationCode_Process(void); + /* USER CODE BEGIN Private defines */ /* In this example TIM2 input clock (TIM2CLK) is set to APB1 clock (PCLK1), diff --git a/Core/Src/cmox_low_level.c b/Core/Src/cmox_low_level.c new file mode 100644 index 0000000..2ca8bbf --- /dev/null +++ b/Core/Src/cmox_low_level.c @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * @file cmox_low_level.c + * @author MCD Application Team + * @brief This file contains Low level functions for CMOX initialization + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 Yunhorn Technology Limited. + * Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file in + * the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +#include "cmox_init.h" +#include "cmox_low_level.h" +#include "stm32wlxx_hal.h" + +/** + * @brief CMOX library low level initialization + * @param pArg User defined parameter that is transmitted from initialize service + * @retval Initialization status: @ref CMOX_INIT_SUCCESS / @ref CMOX_INIT_FAIL + */ +cmox_init_retval_t cmox_ll_init(void *pArg) +{ + (void)pArg; + /* Ensure CRC is enabled for cryptographic processing */ + __HAL_RCC_CRC_RELEASE_RESET(); + __HAL_RCC_CRC_CLK_ENABLE(); + return CMOX_INIT_SUCCESS; +} + +/** + * @brief CMOX library low level de-initialization + * @param pArg User defined parameter that is transmitted from finalize service + * @retval De-initialization status: @ref CMOX_INIT_SUCCESS / @ref CMOX_INIT_FAIL + */ +cmox_init_retval_t cmox_ll_deInit(void *pArg) +{ + (void)pArg; + /* Do not turn off CRC to avoid side effect on other SW parts using it */ + return CMOX_INIT_SUCCESS; +} + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Core/Src/flash_if.c b/Core/Src/flash_if.c index be1887a..b00e7ec 100644 --- a/Core/Src/flash_if.c +++ b/Core/Src/flash_if.c @@ -43,8 +43,8 @@ */ enum { - FLASH_EMPTY = 0, - FLASH_NOT_EMPTY = 1 + FLASH_IF_MEM_EMPTY = 0, + FLASH_IF_MEM_NOT_EMPTY = 1 }; /* USER CODE BEGIN PD */ @@ -52,190 +52,150 @@ enum /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ +/** + * @brief Get internal flash page index from page address + */ +#define PAGE_INDEX(__ADDRESS__) (uint32_t)((((__ADDRESS__) - FLASH_BASE) % FLASH_BANK_SIZE) / FLASH_PAGE_SIZE) + /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ +static uint8_t *pAllocatedBuffer = NULL; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ + +/* Private Functions prototypes: internal flash ------------------------------*/ /** * @brief This function writes a data buffer in flash (data are 64-bit aligned). + * * @note After writing data buffer, the flash content is checked. - * @param pDestination: Start address for target location + * @param pDestination: Start address for target location. It has to be 8 bytes aligned. * @param pSource: pointer on buffer with data to write - * @param uLength: Length of data buffer in byte. It has to be 64-bit aligned. - * @retval HAL Status. + * @param uLength: Length of data buffer in bytes. It has to be 8 bytes aligned. + * @return FLASH_IF_StatusTypedef status */ -static int32_t FLASH_IF_Write_Buffer(uint32_t pDestination, uint8_t *pSource, uint32_t uLength); +static FLASH_IF_StatusTypedef FLASH_IF_INT_Write(void *pDestination, const void *pSource, uint32_t uLength); /** - * @brief This function checks if part of Flash is empty - It handles 32b unaligned address - * @param addr: Start of user flash area - * @param size: number of bytes. - * @retval FLASH_EMPTY or FLASH_NOT_EMPTY. + * @brief This function reads flash + * + * @param pDestination: Start address for target location + * @param pSource: flash address to read + * @param uLength: number of bytes + * @return FLASH_IF_StatusTypedef status */ -static int32_t FLASH_IF_IsEmpty(uint8_t *addr, uint32_t size); +static FLASH_IF_StatusTypedef FLASH_IF_INT_Read(void *pDestination, const void *pSource, uint32_t uLength); + +/** + * @brief This function does an erase of n (depends on Length) pages in user flash area + * + * @param pStart pointer of flash address to be erased + * @param uLength number of bytes + * @return FLASH_IF_StatusTypedef status + */ +static FLASH_IF_StatusTypedef FLASH_IF_INT_Erase(void *pStart, uint32_t uLength); + +/** + * @brief This function checks if part of Flash is empty + * + * @param pStart flash address to check + * @param uLength number of bytes to check. It has to be 8 bytes aligned. + * @return int32_t FLASH_IF_MEM_EMPTY or FLASH_IF_MEM_NOT_EMPTY + */ +static int32_t FLASH_IF_INT_IsEmpty(void *pStart, uint32_t uLength); + +/** + * @brief Clear error flags raised during previous operation + * + * @retval FLASH_IF_StatusTypedef status + */ +static FLASH_IF_StatusTypedef FLASH_IF_INT_Clear_Error(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Exported functions --------------------------------------------------------*/ -int32_t FLASH_IF_Write(uint32_t address, uint8_t *data, uint32_t size, uint8_t *dataTempPage) +FLASH_IF_StatusTypedef FLASH_IF_Init(void *pAllocRamBuffer) { + FLASH_IF_StatusTypedef ret_status = FLASH_IF_OK; + /* USER CODE BEGIN FLASH_IF_Init_1 */ + + /* USER CODE END FLASH_IF_Init_1 */ + pAllocatedBuffer = (uint8_t *)pAllocRamBuffer; + + /* USER CODE BEGIN FLASH_IF_Init_2 */ + + /* USER CODE END FLASH_IF_Init_2 */ + return ret_status; +} + +FLASH_IF_StatusTypedef FLASH_IF_DeInit(void) +{ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_OK; + /* USER CODE BEGIN FLASH_IF_DeInit_1 */ + + /* USER CODE END FLASH_IF_DeInit_1 */ + pAllocatedBuffer = NULL; + + /* USER CODE BEGIN FLASH_IF_DeInit_2 */ + + /* USER CODE END FLASH_IF_DeInit_2 */ + return ret_status; +} + +FLASH_IF_StatusTypedef FLASH_IF_Write(void *pDestination, const void *pSource, uint32_t uLength) +{ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_ERROR; /* USER CODE BEGIN FLASH_IF_Write_1 */ /* USER CODE END FLASH_IF_Write_1 */ - int32_t status = FLASH_OK; - uint32_t page_start_index = PAGE(address); - uint32_t page_end_index = PAGE(address + size - 1); - uint32_t curr_size = size; - uint32_t curr_dest_addr = address; - uint32_t curr_src_addr = (uint32_t)data; - - if ((data == NULL) || ((size % sizeof(uint64_t)) != 0) || ((address % sizeof(uint64_t)) != 0)) + if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pDestination)) { - return FLASH_PARAM_ERROR; + ret_status = FLASH_IF_INT_Write(pDestination, pSource, uLength); } - - if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U) - { - return FLASH_LOCK_ERROR; - } - - if (page_start_index != page_end_index) - { - curr_size = FLASH_PAGE_SIZE - (address % FLASH_PAGE_SIZE); - } - - for (uint32_t idx = page_start_index; idx <= page_end_index; idx++) - { - if (FLASH_IF_IsEmpty((uint8_t *)curr_dest_addr, curr_size) != FLASH_EMPTY) - { - if (dataTempPage == NULL) - { - return FLASH_PARAM_ERROR; - } - /* backup initial Flash page data in RAM area */ - UTIL_MEM_cpy_8(dataTempPage, (uint8_t *)(idx * FLASH_PAGE_SIZE + FLASH_BASE), FLASH_PAGE_SIZE); - /* copy fragment into RAM area */ - UTIL_MEM_cpy_8(&dataTempPage[((uint32_t)curr_dest_addr) % FLASH_PAGE_SIZE], (uint8_t *)curr_src_addr, curr_size); - - /* erase the Flash sector, to avoid writing twice in RAM */ - if (FLASH_IF_EraseByPages(idx, 1, 0) != FLASH_OK) - { - status = FLASH_ERASE_ERROR; - break; /* exit for loop */ - } - else - { - /* copy the whole flash sector including fragment from RAM to Flash*/ - if (FLASH_IF_Write_Buffer(idx * FLASH_PAGE_SIZE + FLASH_BASE, dataTempPage, FLASH_PAGE_SIZE) != FLASH_OK) - { - status = FLASH_WRITE_ERROR; - break; /* exit for loop */ - } - } - } - else - { - if (FLASH_IF_Write_Buffer(curr_dest_addr, (uint8_t *)curr_src_addr, curr_size) != FLASH_OK) - { - status = FLASH_WRITE_ERROR; - break; /* exit for loop */ - } - } - - /* 2nd part of memory overlapped on 2nd flash sector */ - curr_dest_addr += curr_size; - curr_src_addr += curr_size; - curr_size = size - curr_size; - } - - return status; /* USER CODE BEGIN FLASH_IF_Write_2 */ /* USER CODE END FLASH_IF_Write_2 */ + return ret_status; } -int32_t FLASH_IF_Write64(uint32_t address, uint64_t data) +FLASH_IF_StatusTypedef FLASH_IF_Read(void *pDestination, const void *pSource, uint32_t uLength) { - /* USER CODE BEGIN FLASH_IF_Write64_1 */ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_ERROR; + /* USER CODE BEGIN FLASH_IF_Read_1 */ - /* USER CODE END FLASH_IF_Write64_1 */ - while (*(uint64_t *)address != data) + /* USER CODE END FLASH_IF_Read_1 */ + if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pSource)) { - while (LL_FLASH_IsActiveFlag_OperationSuspended()); - HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data); + ret_status = FLASH_IF_INT_Read(pDestination, pSource, uLength); } + /* USER CODE BEGIN FLASH_IF_Read_2 */ - return FLASH_OK; - /* USER CODE BEGIN FLASH_IF_Write64_2 */ - - /* USER CODE END FLASH_IF_Write64_2 */ + /* USER CODE END FLASH_IF_Read_2 */ + return ret_status; } -int32_t FLASH_IF_EraseByPages(uint32_t page, uint16_t n, int32_t interrupt) +FLASH_IF_StatusTypedef FLASH_IF_Erase(void *pStart, uint32_t uLength) { - /* USER CODE BEGIN FLASH_IF_EraseByPages_1 */ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_ERROR; + /* USER CODE BEGIN FLASH_IF_Erase_1 */ - /* USER CODE END FLASH_IF_EraseByPages_1 */ - HAL_StatusTypeDef hal_status; - FLASH_EraseInitTypeDef erase_str; - uint32_t page_error; - - erase_str.TypeErase = FLASH_TYPEERASE_PAGES; - erase_str.Page = page; - erase_str.NbPages = n; - - /* Erase the Page */ - if (interrupt) + /* USER CODE END FLASH_IF_Erase_1 */ + /* Check Flash start address */ + if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pStart)) { - hal_status = HAL_FLASHEx_Erase_IT(&erase_str); - } - else - { - hal_status = HAL_FLASHEx_Erase(&erase_str, &page_error); + ret_status = FLASH_IF_INT_Erase(pStart, uLength); } + /* USER CODE BEGIN FLASH_IF_Erase_2 */ - return ((hal_status == HAL_OK) ? FLASH_OK : ((hal_status == HAL_BUSY) ? FLASH_BUSY : FLASH_ERASE_ERROR)); - /* USER CODE BEGIN FLASH_IF_EraseByPages_2 */ - - /* USER CODE END FLASH_IF_EraseByPages_2 */ -} - -void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) -{ - /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_1 */ - - /* USER CODE END HAL_FLASH_EndOfOperationCallback_1 */ - /* Call CleanUp callback when all requested pages have been erased */ - if (ReturnValue == 0xFFFFFFFFUL) - { - HWCB_FLASH_EndOfCleanup(); - } - /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_2 */ - - /* USER CODE END HAL_FLASH_EndOfOperationCallback_2 */ -} - -void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue) -{ - /* USER CODE BEGIN HAL_FLASH_OperationErrorCallback_1 */ - - /* USER CODE END HAL_FLASH_OperationErrorCallback_1 */ -} - -void HWCB_FLASH_EndOfCleanup(void) -{ - /* USER CODE BEGIN HWCB_FLASH_EndOfCleanup_1 */ - - /* USER CODE END HWCB_FLASH_EndOfCleanup_1 */ + /* USER CODE END FLASH_IF_Erase_2 */ + return ret_status; } /* USER CODE BEGIN EF */ @@ -243,86 +203,282 @@ void HWCB_FLASH_EndOfCleanup(void) /* USER CODE END EF */ /* Private Functions Definition -----------------------------------------------*/ -static int32_t FLASH_IF_Write_Buffer(uint32_t pDestination, uint8_t *pSource, uint32_t uLength) + +/* Private Functions : internal flash -----------------------------------------*/ +static FLASH_IF_StatusTypedef FLASH_IF_INT_Write(void *pDestination, const void *pSource, uint32_t uLength) { - /* USER CODE BEGIN FLASH_IF_Write_Buffer_1 */ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_OK; + /* USER CODE BEGIN FLASH_IF_INT_Write_1 */ - /* USER CODE END FLASH_IF_Write_Buffer_1 */ - uint8_t *pSrc = pSource; - uint64_t src_value; - int32_t status = FLASH_OK; + /* USER CODE END FLASH_IF_INT_Write_1 */ + uint32_t uDest = (uint32_t)pDestination; + uint32_t uSource = (uint32_t)pSource; + uint32_t length = uLength; + uint32_t page_index; + uint32_t address_offset; + uint32_t start_page_index; + uint32_t page_address; + uint32_t number_pages; + uint32_t current_dest; + uint32_t current_source; + uint32_t current_length; - for (uint32_t i = 0; i < (uLength / sizeof(uint64_t)); i++) + if ((pDestination == NULL) || (pSource == NULL) || !IS_ADDR_ALIGNED_64BITS(uLength) + || !IS_ADDR_ALIGNED_64BITS((uint32_t)pDestination)) { - UTIL_MEM_cpy_8(&src_value, pSrc, sizeof(uint64_t)); - - /* Avoid writing 0xFFFFFFFFFFFFFFFFLL on erased Flash */ - if (src_value != UINT64_MAX) - { - status = FLASH_IF_Write64(pDestination, src_value); - } - - pDestination += sizeof(uint64_t); - pSrc += sizeof(uint64_t); - - if (status != FLASH_OK) - { - /* exit the for loop*/ - break; - } + return FLASH_IF_PARAM_ERROR; } - return status; - /* USER CODE BEGIN FLASH_IF_Write_Buffer_2 */ + /* Clear error flags raised during previous operation */ + ret_status = FLASH_IF_INT_Clear_Error(); - /* USER CODE END FLASH_IF_Write_Buffer_2 */ + if (ret_status == FLASH_IF_OK) + { + /* Unlock the Flash to enable the flash control register access */ + if (HAL_FLASH_Unlock() == HAL_OK) + { + start_page_index = PAGE_INDEX(uDest); + number_pages = PAGE_INDEX(uDest + uLength - 1U) - start_page_index + 1U; + + if (number_pages > 1) + { + length = FLASH_PAGE_SIZE - (uDest % FLASH_PAGE_SIZE); + } + + for (page_index = start_page_index; page_index < (start_page_index + number_pages); page_index++) + { + page_address = page_index * FLASH_PAGE_SIZE + FLASH_BASE; + if (FLASH_IF_INT_IsEmpty(pDestination, length) != FLASH_IF_MEM_EMPTY) + { + if (pAllocatedBuffer == NULL) + { + ret_status = FLASH_IF_PARAM_ERROR; + break; /* exit for loop */ + } + + /* backup initial Flash page data in RAM area */ + FLASH_IF_INT_Read(pAllocatedBuffer, (const void *)page_address, FLASH_PAGE_SIZE); + /* copy fragment into RAM area */ + UTIL_MEM_cpy_8(&pAllocatedBuffer[uDest % FLASH_PAGE_SIZE], (const void *)uSource, length); + + /* erase the Flash sector, to avoid writing twice in RAM */ + if (FLASH_IF_INT_Erase((void *)page_address, FLASH_PAGE_SIZE) != FLASH_IF_OK) + { + ret_status = FLASH_IF_ERASE_ERROR; + break; /* exit for loop */ + } + + /* copy the whole flash sector including fragment from RAM to Flash */ + current_dest = page_address; + current_source = (uint32_t)pAllocatedBuffer; + current_length = FLASH_PAGE_SIZE; + } + else + { + /* write a part of flash page from selected source data */ + current_dest = uDest; + current_source = uSource; + current_length = length; + } + + for (address_offset = 0U; address_offset < current_length; address_offset += 8U) + { + /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word */ + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, current_dest, + *((uint64_t *)(current_source + address_offset))) == HAL_OK) + { + /* Check the written value */ + if (*(uint64_t *)current_dest != *(uint64_t *)(current_source + address_offset)) + { + /* Flash content doesn't match SRAM content */ + ret_status = FLASH_IF_WRITE_ERROR; + break; + } + /* Increment FLASH Destination address */ + current_dest = current_dest + 8U; + } + else + { + /* Error occurred while writing data in Flash memory */ + ret_status = FLASH_IF_WRITE_ERROR; + break; + } + } + + if (ret_status != FLASH_IF_OK) + { + /* Error occurred while writing data in Flash memory */ + break; + } + + /* Increment FLASH destination address, source address, and decrease remaining length */ + uDest += length; + uSource += length; + length = ((uLength - length) > FLASH_PAGE_SIZE) ? FLASH_PAGE_SIZE : uLength - length; + } + + /* Lock the Flash to disable the flash control register access (recommended + * to protect the FLASH memory against possible unwanted operation) */ + HAL_FLASH_Lock(); + } + else + { + ret_status = FLASH_IF_LOCK_ERROR; + } + } + /* USER CODE BEGIN FLASH_IF_INT_Write_2 */ + + /* USER CODE END FLASH_IF_INT_Write_2 */ + return ret_status; } -static int32_t FLASH_IF_IsEmpty(uint8_t *addr, uint32_t size) +static FLASH_IF_StatusTypedef FLASH_IF_INT_Read(void *pDestination, const void *pSource, uint32_t uLength) { - /* USER CODE BEGIN FLASH_IF_IsEmpty_1 */ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_OK; + /* USER CODE BEGIN FLASH_IF_INT_Read_1 */ - /* USER CODE END FLASH_IF_IsEmpty_1 */ - uint64_t *addr64; - uint32_t i; - - /* start memory NOT 64bits aligned */ - while ((((uint32_t)addr) % sizeof(uint64_t)) != 0) + /* USER CODE END FLASH_IF_INT_Read_1 */ + if ((pDestination == NULL) || (pSource == NULL)) { - if (*addr++ != UINT8_MAX) - { - return FLASH_NOT_EMPTY; - } - size--; + return FLASH_IF_PARAM_ERROR; } - /* addr64 is 64 bits aligned */ - addr64 = (uint64_t *)addr; - for (i = 0; i < (size / sizeof(uint64_t)); i++) + UTIL_MEM_cpy_8(pDestination, pSource, uLength); + /* USER CODE BEGIN FLASH_IF_INT_Read_2 */ + + /* USER CODE END FLASH_IF_INT_Read_2 */ + return ret_status; +} + +static FLASH_IF_StatusTypedef FLASH_IF_INT_Erase(void *pStart, uint32_t uLength) +{ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_OK; + /* USER CODE BEGIN FLASH_IF_INT_Erase_1 */ + + /* USER CODE END FLASH_IF_INT_Erase_1 */ + HAL_StatusTypeDef hal_status = HAL_ERROR; + uint32_t page_error = 0U; + uint32_t uStart = (uint32_t)pStart; + FLASH_EraseInitTypeDef erase_init; + + if (pStart == NULL) { - if (*addr64++ != UINT64_MAX) + return FLASH_IF_PARAM_ERROR; + } + + /* Clear error flags raised during previous operation */ + ret_status = FLASH_IF_INT_Clear_Error(); + + if (ret_status == FLASH_IF_OK) + { + /* Unlock the Flash to enable the flash control register access */ + if (HAL_FLASH_Unlock() == HAL_OK) { - return FLASH_NOT_EMPTY; + erase_init.TypeErase = FLASH_TYPEERASE_PAGES; + erase_init.Page = PAGE_INDEX(uStart); + /* Get the number of pages to erase from 1st page */ + erase_init.NbPages = PAGE_INDEX(uStart + uLength - 1U) - erase_init.Page + 1U; + + /* Erase the Page */ + hal_status = HAL_FLASHEx_Erase(&erase_init, &page_error); + + if (hal_status != HAL_OK) + { + ret_status = (hal_status == HAL_BUSY) ? FLASH_IF_BUSY : FLASH_IF_ERASE_ERROR; + } + + /* Lock the Flash to disable the flash control register access (recommended + * to protect the FLASH memory against possible unwanted operation) */ + HAL_FLASH_Lock(); + } + else + { + ret_status = FLASH_IF_LOCK_ERROR; } } - size -= sizeof(uint64_t) * i; + /* USER CODE BEGIN FLASH_IF_INT_Erase_2 */ - /* end memory NOT 64 bits aligned */ - addr = (uint8_t *)addr64; - while (size != 0) + /* USER CODE END FLASH_IF_INT_Erase_2 */ + return ret_status; +} + +static int32_t FLASH_IF_INT_IsEmpty(void *pStart, uint32_t uLength) +{ + int32_t status = FLASH_IF_MEM_EMPTY; + /* USER CODE BEGIN FLASH_IF_INT_IsEmpty_1 */ + + /* USER CODE END FLASH_IF_INT_IsEmpty_1 */ + uint32_t index; + for (index = 0; index < uLength; index += 8) { - if (*addr++ != UINT8_MAX) + if (*(uint64_t *)pStart != UINT64_MAX) { - return FLASH_NOT_EMPTY; + status = FLASH_IF_MEM_NOT_EMPTY; + break; } - size--; + pStart = (void *)((uint32_t)pStart + 8U); } - return FLASH_EMPTY; - /* USER CODE BEGIN FLASH_IF_IsEmpty_2 */ + /* USER CODE BEGIN FLASH_IF_INT_IsEmpty_2 */ - /* USER CODE END FLASH_IF_IsEmpty_2 */ + /* USER CODE END FLASH_IF_INT_IsEmpty_2 */ + return status; +} + +static FLASH_IF_StatusTypedef FLASH_IF_INT_Clear_Error(void) +{ + FLASH_IF_StatusTypedef ret_status = FLASH_IF_LOCK_ERROR; + /* USER CODE BEGIN FLASH_IF_INT_Clear_Error_1 */ + + /* USER CODE END FLASH_IF_INT_Clear_Error_1 */ + /* Unlock the Program memory */ + if (HAL_FLASH_Unlock() == HAL_OK) + { + /* Clear all FLASH flags */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + /* Unlock the Program memory */ + if (HAL_FLASH_Lock() == HAL_OK) + { + ret_status = FLASH_IF_OK; + } + } + /* USER CODE BEGIN FLASH_IF_INT_Clear_Error_2 */ + + /* USER CODE END FLASH_IF_INT_Clear_Error_2 */ + return ret_status; } /* USER CODE BEGIN PrFD */ /* USER CODE END PrFD */ + +/* HAL overload functions ---------------------------------------------------------*/ +/** + * @note This function overwrites the __weak one from HAL + */ +void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) +{ + /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_1 */ + + /* USER CODE END HAL_FLASH_EndOfOperationCallback_1 */ + if (ReturnValue == 0xFFFFFFFFUL) + { + /* Call when all requested pages have been erased */ + } + /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_2 */ + + /* USER CODE END HAL_FLASH_EndOfOperationCallback_2 */ +} + +/** + * @note This function overwrites the __weak one from HAL + */ +void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue) +{ + /* USER CODE BEGIN HAL_FLASH_OperationErrorCallback_1 */ + + /* USER CODE END HAL_FLASH_OperationErrorCallback_1 */ +} + +/* USER CODE BEGIN Overload_HAL_weaks */ + +/* USER CODE END Overload_HAL_weaks */ diff --git a/Core/Src/sts_cmox_hmac_sha.c b/Core/Src/sts_cmox_hmac_sha.c new file mode 100644 index 0000000..ed4438e --- /dev/null +++ b/Core/Src/sts_cmox_hmac_sha.c @@ -0,0 +1,90 @@ +/** + ****************************************************************************** + * @file sts_cmox_hmac_sha.c * + * @author Yunhorn (r) Technology Limited Application Team * + * @brief Yunhorn (r) SmarToilets (r) HMAC-SHA1 Process file. * + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 Yunhorn Technology Limited. + * Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd. + * All rights reserved. + ****************************************************************************** + */ +#include "main.h" +#include "string.h" +#include "cmox_init.h" +#include "cmox_low_level.h" +#include "stm32wlxx_hal.h" +#include "sts_cmox_hmac_sha.h" +#include "yunhorn_sts_prd_conf.h" +#include "sys_app.h" + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +const uint8_t mKey[] = +{ + 0x59,0x75,0x33,0x6e,0x31,0x48,0x34,0x4f,0x31,0x52,0x35,0x4e,0x39,0x53,0x32,0x54,0x36,0x53 +}; + +uint8_t Computed_Tag_SHA1[YUNHORN_STS_AC_CODE_SIZE]={0x0}; +extern volatile uint8_t sts_ac_code[YUNHORN_STS_AC_CODE_SIZE]; +hmac_result_t hmac_result; + +uint32_t sts_hmac_verify(void) +{ + uint8_t i=0; + uint8_t uid[8]=""; + uint32_t ret=0; + hmac_result.ac_pass = 60; + hmac_result.hmac_tag_size = 0; + GetUniqueId(uid); + + ret = sts_hmac_sha1((const uint8_t *) mKey, sizeof(mKey), (const uint8_t*)(uid+4), 4, &hmac_result); + for (i=0;ihmac_tag, Computed_Tag_SHA1, sizeof(Computed_Tag_SHA1)); + hmac_result->hmac_tag_size = computed_size; + + return retval; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/LoRaWAN/App/lora_app.c b/LoRaWAN/App/lora_app.c index 30622ce..0b96810 100644 --- a/LoRaWAN/App/lora_app.c +++ b/LoRaWAN/App/lora_app.c @@ -39,19 +39,34 @@ /* USER CODE BEGIN Includes */ #include "yunhorn_sts_sensors.h" #include "yunhorn_sts_motion_sensor.h" +#include "sts_cmox_hmac_sha.h" /* USER CODE END Includes */ /* External variables ---------------------------------------------------------*/ /* USER CODE BEGIN EV */ volatile uint8_t mems_int1_detected = 0; volatile uint32_t periodicity_length=0; +volatile uint8_t sts_service_mask; +volatile uint32_t rfac_timer=0; +extern hmac_result_t hmac_result; +volatile uint8_t sts_work_mode =0; +volatile uint8_t sts_ac_code[YUNHORN_STS_AC_CODE_SIZE]={0x0}; volatile uint8_t heart_beat_timer=0, sts_lorawan_joined=0; -volatile sts_cfg_nvm_t sts_cfg_nvm={sts_mtmcode1,sts_mtmcode2, sts_version, sts_hardware_ver, 0x00,0x05,'M',0x03,0x08,0x04,0x02}; +volatile sts_cfg_nvm_t sts_cfg_nvm={sts_mtmcode1,sts_mtmcode2, sts_version, sts_hardware_ver, +0x00,'M', 0x05,'M', 0x04,0x00,0x00,0x20, +{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}, + 0x01,0x03,0x00,0x02, + {0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,0x0} +}; +volatile uint32_t SamplingPeriodicity = 1000; //unit ms +volatile uint32_t HeartBeatPeriodicity = 120000; //unit ms + #ifdef YUNHORN_STS_M7_ENABLED extern volatile uint8_t sensor_data_ready; extern volatile STS_M7_SensorDataTypeDef sts_m7_sensorData; extern volatile uint8_t act_threshold, inact_threshold, inact_duration; #endif +char outbuf[64]=""; /* USER CODE END EV */ /* Private typedef -----------------------------------------------------------*/ @@ -95,7 +110,7 @@ typedef enum TxEventType_e * @brief LoRaWAN NVM Flash address * @note last 2 sector of a 128kBytes device */ -#define LORAWAN_NVM_BASE_ADDRESS ((uint32_t)0x0803F000UL) +#define LORAWAN_NVM_BASE_ADDRESS ((void *)0x0803F000UL) /* USER CODE BEGIN PD */ static const char *slotStrings[] = { "1", "2", "C", "C_MC", "P", "P_MC" }; @@ -341,6 +356,11 @@ static UTIL_TIMER_Object_t RxLedTimer; */ static UTIL_TIMER_Object_t JoinLedTimer; +/** + * @brief Timer to handle the YunHorn STS Sensor Heart Beat Process + */ +static UTIL_TIMER_Object_t YunhornSTSHeartBeatTimer; + /* USER CODE END PV */ /* Exported functions ---------------------------------------------------------*/ @@ -439,6 +459,7 @@ void LoRaWAN_Init(void) UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP1), UTIL_SEQ_RFU, STS_MOTION_SENSOR_WakeUp_Process); UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventP2), UTIL_SEQ_RFU, STS_SENSOR_Function_Test_Process); + UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_YunhornSTSEventRFAC), UTIL_SEQ_RFU, STS_YunhornSTSEventRFAC_Process); STS_REBOOT_CONFIG_Init(); @@ -591,10 +612,30 @@ static void OnRxData(LmHandlerAppData_t *appData, LmHandlerRxParams_t *params) /* USER CODE END OnRxData_1 */ } +/** + * @brief Yunhorn STS Sensor Heart Beat Timer callback function + * @param context ptr of STS Sampling Check context + */ +static void OnYunhornSTSHeartBeatTimerEvent(void *context) +{ + heart_beat_timer = 1; + UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LoRaSendOnTxTimerOrButtonEvent), CFG_SEQ_Prio_0); + UTIL_TIMER_Start(&YunhornSTSHeartBeatTimer); + + if ((sts_lorawan_joined ) && (sts_ac_code[0]==0x0)) + { + /* RFAC Challenge */ + if (rfac_timer < (STS_BURN_IN_RFAC+3)) { + rfac_timer ++; + } + UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_YunhornSTSEventRFAC), CFG_SEQ_Prio_0); + } +} + void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) { uint8_t i=0; - char outbuf[64]=""; + /* * YUNHORN STS PRODUCT BOARD LEVEL CONTROL OR REPORT @@ -627,10 +668,27 @@ void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf); } break; - + case 'M': //"YM" + if ((char)tlv_buf[CFG_CMD3] >= '0' && (char)tlv_buf[CFG_CMD3]<='9') // Service Mask "YZM" + { + sts_service_mask = (uint8_t)(tlv_buf[CFG_CMD3]-0x30)&0xFF; + sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask; + outbuf[i++] = (uint8_t) 'Y'; + outbuf[i++] = (uint8_t) 'M'; + outbuf[i++] = (uint8_t) (sts_service_mask+0x30); + STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf); + APP_LOG(TS_OFF, VLEVEL_H, ">>>>>>>>>>>>>>>>>>>>> Mask = [ %02x ] \r\n", sts_service_mask); + OnStoreSTSCFGContextRequest(); + #ifdef YUNHORN_STS_O6_ENABLED + if (sts_service_mask != STS_SERVICE_MASK_L0) STS_Lamp_Bar_Set_Dark(); + STS_Combined_Status_Processing(); + #endif + } + break; case 'V': //"YV" if ((char)tlv_buf[CFG_CMD3] == 'H') { // "YVH" REPORT FIRMWARE VERSION "YVH" // FIRMWARE VERSION REPORT + i = 0; outbuf[i++] = (uint8_t) 'V'; outbuf[i++] = (uint8_t) sts_mtmcode1; outbuf[i++] = (uint8_t) sts_mtmcode2; @@ -645,23 +703,29 @@ void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) else if ((char)tlv_buf[CFG_CMD3] == 'C') { // "YVC" REPORT NVM STORED CONFIG PARAMETERS "YVC" - uint8_t cfg_in_nvm[YUNHORN_STS_MAX_NVM_CFG_SIZE]=""; + uint8_t cfg_in_nvm[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0}; OnRestoreSTSCFGContextRequest((uint8_t *)cfg_in_nvm); outbuf[i++] = (uint8_t) 'C'; outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_MTM1]; //MTM Code outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_MTM2]; //MTM Code outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_VER]; //STS Version - outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_PERIODICITY_H]; //Periodicity count high - outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_PERIODICITY_L]; //Periodicity count low - outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_UNIT]; //Periodicity unit - outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN]; //length of following cfg value + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_HWV]; //STS Version + outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_PERIODICITY]); //UPLINK Periodicity + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_UNIT]; //UPLINK Periodicity unit + outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_SAMPLING]); //Heart-beat or SAMPLING Periodicity + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_S_UNIT]; //Heart-beat or SAMPLING Periodicity unit + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_WORK_MODE]; // STS WORK MODE + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_SERVICE_MASK]; //service mask + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_RESERVE01]; //service mask + outbuf[i++] = (uint8_t) cfg_in_nvm[NVM_LEN]; //length of following cfg value - for (uint8_t j=1; j <= cfg_in_nvm[NVM_LEN]; j++) { + + for (uint8_t j=0; j <= cfg_in_nvm[NVM_LEN]; j++) { outbuf[i++] = (uint8_t) (cfg_in_nvm[NVM_LEN+j]); } STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf); - APP_LOG(TS_OFF, VLEVEL_L, "###### YUNHORN Report Config in NVM [ %10x ] \r\n", outbuf); + APP_LOG(TS_OFF, VLEVEL_H, "###### YUNHORN Report Config in NVM [ %10x ] \r\n", outbuf); } break; @@ -713,19 +777,15 @@ void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) { periodicity_length = (tlv_buf[CFG_CMD3]-0x30)*10+ (tlv_buf[CFG_CMD4]-0x30); uint8_t periodicity_unit = (char)tlv_buf[CFG_CMD5]; - - - if ((char)tlv_buf[CFG_CMD5] == 'M') { + if ((char)tlv_buf[CFG_CMD5] == 'M') { periodicity_length *= 60; - } else if ((char)tlv_buf[CFG_CMD5] == 'H') { + } else if ((char)tlv_buf[CFG_CMD5] == 'H') { periodicity_length *= 3600; - } else if ((char)tlv_buf[CFG_CMD5] == 'S') { - - if (periodicity_length < 10) periodicity_length = 10; - } - - OnTxPeriodicityChanged(periodicity_length*1000); //translate to 1000ms=1s + TxPeriodicity = periodicity_length*1000; //translate to 1000ms=1s + HeartBeatPeriodicity = TxPeriodicity; + + OnTxPeriodicityChanged(TxPeriodicity); i = 0; outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD1]; outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD2]; @@ -735,18 +795,14 @@ void USER_APP_AUTO_RESPONDER_Parse(char *tlv_buf, size_t tlv_buf_size) STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf); // Save config to NVM - sts_cfg_nvm.mtmcode1 = sts_mtmcode1; - sts_cfg_nvm.mtmcode2 = sts_mtmcode2; - sts_cfg_nvm.version = sts_version; - sts_cfg_nvm.hardware_ver = sts_hardware_ver; - sts_cfg_nvm.periodicity_h = (tlv_buf[CFG_CMD3]-0x30); - sts_cfg_nvm.periodicity_l = (tlv_buf[CFG_CMD4]-0x30); - if (((char)tlv_buf[CFG_CMD5] == 'S') && (periodicity_length == 10)) - { - sts_cfg_nvm.periodicity_h = 0X01; - sts_cfg_nvm.periodicity_l = 0X00; - } - sts_cfg_nvm.unit = periodicity_unit; + sts_cfg_nvm.mtmcode1 = (uint8_t)sts_mtmcode1; + sts_cfg_nvm.mtmcode2 = (uint8_t)sts_mtmcode2; + sts_cfg_nvm.version = (uint8_t)sts_version; + sts_cfg_nvm.hardware_ver = (uint8_t)sts_hardware_ver; + sts_cfg_nvm.periodicity = (uint8_t)((tlv_buf[CFG_CMD3]-0x30)*10+(tlv_buf[CFG_CMD4]-0x30)); + sts_cfg_nvm.unit = (uint8_t)tlv_buf[CFG_CMD5]; + sts_cfg_nvm.work_mode = (uint8_t)sts_work_mode; + sts_cfg_nvm.sts_service_mask = (uint8_t)sts_service_mask; OnStoreSTSCFGContextRequest(); APP_LOG(TS_OFF, VLEVEL_L, "###### YUNHORN Periodicity Changed to [ %d ] Seconds\r\n", periodicity_length); @@ -1346,13 +1402,9 @@ static void OnStoreContextRequest(void *nvm, uint32_t nvm_size) /* USER CODE END OnStoreContextRequest_1 */ /* store nvm in flash */ - if (HAL_FLASH_Unlock() == HAL_OK) + if (FLASH_IF_Erase(LORAWAN_NVM_BASE_ADDRESS, FLASH_PAGE_SIZE) == FLASH_IF_OK) { - if (FLASH_IF_EraseByPages(PAGE(LORAWAN_NVM_BASE_ADDRESS), 1, 0U) == FLASH_OK) - { - FLASH_IF_Write(LORAWAN_NVM_BASE_ADDRESS, (uint8_t *)nvm, nvm_size, NULL); - } - HAL_FLASH_Lock(); + FLASH_IF_Write(LORAWAN_NVM_BASE_ADDRESS, (const void *)nvm, nvm_size); } /* USER CODE BEGIN OnStoreContextRequest_Last */ @@ -1364,7 +1416,7 @@ static void OnRestoreContextRequest(void *nvm, uint32_t nvm_size) /* USER CODE BEGIN OnRestoreContextRequest_1 */ /* USER CODE END OnRestoreContextRequest_1 */ - UTIL_MEM_cpy_8(nvm, (void *)LORAWAN_NVM_BASE_ADDRESS, nvm_size); + FLASH_IF_Read(nvm, LORAWAN_NVM_BASE_ADDRESS, nvm_size); /* USER CODE BEGIN OnRestoreContextRequest_Last */ /* USER CODE END OnRestoreContextRequest_Last */ @@ -1373,20 +1425,34 @@ static void OnRestoreContextRequest(void *nvm, uint32_t nvm_size) void OnStoreSTSCFGContextRequest(void) { /* USER CODE BEGIN OnStoreContextRequest_1 */ - uint8_t i=0, nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]="", nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE; + uint8_t i=0, j=0, nvm_store_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0}, nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE; #ifdef YUNHORN_STS_M7_ENABLED - sts_cfg_nvm.length = (uint8_t) NVM_CFG_PARAMETER_SIZE; - nvm_store_value[i++] = (uint8_t) sts_mtmcode1; - nvm_store_value[i++] = (uint8_t) sts_mtmcode2; - nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.version; - nvm_store_value[i++] = (uint8_t) sts_hardware_ver; - nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.periodicity_h; - nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.periodicity_l; - nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.unit; - nvm_store_value[i++] = (uint8_t) sts_cfg_nvm.length; - for (uint8_t j=0;j< NVM_CFG_PARAMETER_SIZE; j++) { - nvm_store_value[i+j] = (uint8_t) (sts_cfg_nvm.p[j]); + sts_cfg_nvm.length = STS_NVM_CFG_SIZE; + nvm_store_value[i++] = sts_cfg_nvm.mtmcode1; + nvm_store_value[i++] = sts_cfg_nvm.mtmcode2; + nvm_store_value[i++] = sts_cfg_nvm.version; + nvm_store_value[i++] = sts_cfg_nvm.hardware_ver; + nvm_store_value[i++] = sts_cfg_nvm.periodicity; + nvm_store_value[i++] = sts_cfg_nvm.unit; + nvm_store_value[i++] = sts_cfg_nvm.sampling; + nvm_store_value[i++] = sts_cfg_nvm.s_unit; + nvm_store_value[i++] = sts_cfg_nvm.work_mode; + nvm_store_value[i++] = sts_cfg_nvm.sts_service_mask; + nvm_store_value[i++] = sts_cfg_nvm.reseve01; + nvm_store_value[i++] = (uint8_t) STS_NVM_CFG_SIZE; //sts_cfg_nvm.length; + + for (j = 0; j < STS_CFG_PCFG_SIZE; j++) { + nvm_store_value[i++] = (sts_cfg_nvm.p[j]); + } + + nvm_store_value[i++] = sts_cfg_nvm.fall_detection_acc_threshold; + nvm_store_value[i++] = sts_cfg_nvm.fall_detection_depth_threshold; + nvm_store_value[i++] = sts_cfg_nvm.fall_detection_reserve; + nvm_store_value[i++] = sts_cfg_nvm.occupancy_overtime_threshold; + + for (j = 0; j < YUNHORN_STS_AC_CODE_SIZE; j++) { + nvm_store_value[i++] = (sts_cfg_nvm.ac[j]); } #endif @@ -1399,13 +1465,9 @@ void OnStoreSTSCFGContextRequest(void) #endif /* USER CODE END OnStoreContextRequest_1 */ /* store nvm in flash */ - if (HAL_FLASH_Unlock() == HAL_OK) + if (FLASH_IF_Erase(STS_CONFIG_NVM_BASE_ADDRESS, FLASH_PAGE_SIZE) == FLASH_IF_OK) { - if (FLASH_IF_EraseByPages(PAGE(STS_CONFIG_NVM_BASE_ADDRESS), 1, 0U) == FLASH_OK) - { - FLASH_IF_Write(STS_CONFIG_NVM_BASE_ADDRESS, nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE, NULL); - } - HAL_FLASH_Lock(); + FLASH_IF_Write(STS_CONFIG_NVM_BASE_ADDRESS, (const void *)nvm_store_value, YUNHORN_STS_MAX_NVM_CFG_SIZE); } /* USER CODE BEGIN OnStoreContextRequest_Last */ @@ -1438,30 +1500,42 @@ void OnRestoreSTSCFGContextRequest(uint8_t *cfg_in_nvm) void STS_REBOOT_CONFIG_Init(void) { /* USER CODE BEGIN OnRestoreContextRequest_1 */ - uint8_t i=0, nvm_stored_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]="", nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE; + uint8_t i=0, nvm_stored_value[YUNHORN_STS_MAX_NVM_CFG_SIZE]={0x0}, nvm_store_size=YUNHORN_STS_MAX_NVM_CFG_SIZE; /* USER CODE END OnRestoreContextRequest_1 */ UTIL_MEM_cpy_8(nvm_stored_value, (void *)STS_CONFIG_NVM_BASE_ADDRESS, nvm_store_size); /* USER CODE BEGIN OnRestoreContextRequest_Last */ #ifdef YUNHORN_STS_M7_ENABLED - - if ((nvm_stored_value[0] == 0xFF) || (nvm_stored_value[1] == 0xFF) ||(nvm_stored_value[2] == 0xFF)) + if ((nvm_stored_value[NVM_MTM1] != sts_mtmcode1) || (nvm_stored_value[NVM_MTM2] != sts_mtmcode2) || (nvm_stored_value[NVM_VER] != sts_version)) { - APP_LOG(TS_OFF, VLEVEL_L, "Initial Boot with Empty Config, Flash with default config....\r\n"); - OnStoreSTSCFGContextRequest(); - } else + APP_LOG(TS_OFF, VLEVEL_H, "\r\nInitial Boot with Empty Config, Flash with default config....\r\n"); + OnStoreSTSCFGContextRequest(); + UTIL_MEM_set_8((void *)sts_ac_code, 0x00, YUNHORN_STS_AC_CODE_SIZE); + HAL_Delay(1000); + } else { - sts_cfg_nvm.mtmcode1 = (uint8_t)nvm_stored_value[NVM_MTM1]; - sts_cfg_nvm.mtmcode2 = (uint8_t)nvm_stored_value[NVM_MTM2]; - sts_cfg_nvm.version = (uint8_t)nvm_stored_value[NVM_VER]; - sts_cfg_nvm.hardware_ver = (uint8_t)nvm_stored_value[NVM_HWV]; - sts_cfg_nvm.periodicity_h = (uint8_t)(nvm_stored_value[NVM_PERIODICITY_H]); - sts_cfg_nvm.periodicity_l = (uint8_t)(nvm_stored_value[NVM_PERIODICITY_L]); - sts_cfg_nvm.unit = (uint8_t)(nvm_stored_value[NVM_UNIT]); - sts_cfg_nvm.length = (uint8_t)(nvm_stored_value[NVM_LEN]&0x1F); //MAX 32 bytes + sts_cfg_nvm.periodicity = (uint8_t)(nvm_stored_value[NVM_PERIODICITY]); //TxPeriodicity interval + sts_cfg_nvm.unit = (uint8_t)(nvm_stored_value[NVM_UNIT]); + sts_cfg_nvm.sampling = (uint8_t)(nvm_stored_value[NVM_SAMPLING]); //Heart-beat or sampling interval + sts_cfg_nvm.s_unit = (uint8_t)(nvm_stored_value[NVM_S_UNIT]); + sts_cfg_nvm.work_mode = (uint8_t)(nvm_stored_value[NVM_WORK_MODE]); + sts_cfg_nvm.sts_service_mask = (uint8_t)(nvm_stored_value[NVM_SERVICE_MASK]); + sts_cfg_nvm.reseve01 = (uint8_t)(nvm_stored_value[NVM_RESERVE01]); + sts_cfg_nvm.length = (uint8_t)(nvm_stored_value[NVM_LEN]&0x3F); //MAX 32 bytes + for (uint8_t j=0; j< sts_cfg_nvm.length; j++) { - sts_cfg_nvm.p[j] = (uint8_t)nvm_stored_value[NVM_LEN+1+j]; + sts_cfg_nvm.p[j] = (uint8_t)nvm_stored_value[NVM_LEN+j]; } + + sts_cfg_nvm.fall_detection_acc_threshold = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_ACC_THRESHOLD]; + sts_cfg_nvm.fall_detection_depth_threshold = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_DEPTH_THRESHOLD]; + sts_cfg_nvm.fall_detection_reserve = (uint8_t)nvm_stored_value[NVM_FALL_DETECTION_RESERVE]; + sts_cfg_nvm.occupancy_overtime_threshold = (uint8_t)nvm_stored_value[NVM_OCCUPANCY_OVERTIME_THRESHOLD]; + + for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++) { + sts_cfg_nvm.ac[j] = (uint8_t)nvm_stored_value[NVM_AC_CODE_START +j]; + } + } #endif @@ -1480,7 +1554,7 @@ void STS_REBOOT_CONFIG_Init(void) void OnRestoreSTSCFGContextProcess(void) { - periodicity_length = (sts_cfg_nvm.periodicity_h)*10+(sts_cfg_nvm.periodicity_l); + periodicity_length = (sts_cfg_nvm.periodicity); if ((char)sts_cfg_nvm.unit =='M') { periodicity_length *= 60; } else if ((char) sts_cfg_nvm.unit =='H') { @@ -1498,6 +1572,13 @@ void OnRestoreSTSCFGContextProcess(void) OnTxPeriodicityChanged(TxPeriodicity); } + sts_work_mode = sts_cfg_nvm.work_mode; + sts_service_mask = sts_cfg_nvm.sts_service_mask; + + for (uint8_t j=0; j< YUNHORN_STS_AC_CODE_SIZE; j++) + { + sts_ac_code[j] = sts_cfg_nvm.ac[j]; + } #ifdef YUNHORN_STS_M7_ENABLED if ((sts_version == sts_cfg_nvm.version)&& (NVM_CFG_PARAMETER_SIZE == sts_cfg_nvm.length)) { @@ -1572,3 +1653,38 @@ void STS_SENSOR_Function_Test_Process(void) STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, i, outbuf); } + +void STS_YunhornAuthenticationCode_Process(void) +{ + if (sts_ac_code[0] == 0x00) { + APP_LOG(TS_OFF,VLEVEL_H, "Initial AC CODE blank... \r\n"); + return; + } + + sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0; + if (sts_service_mask == STS_SERVICE_MASK_L2) { + sts_ac_code[0] = 0x0; + } + APP_LOG(TS_OFF, VLEVEL_H, "STS_SERVICE_MASK:%d \r\n",sts_service_mask); +} + +void STS_YunhornSTSEventRFAC_Process(void) +{ + if (sts_ac_code[0] ==0x0) + { + if ((rfac_timer >= STS_BURN_IN_RFAC) && (rfac_timer < (STS_BURN_IN_RFAC +3))) + { + APP_LOG(TS_OFF, VLEVEL_H, "\r\n -------------------RFAC Process\r\n"); + STS_SENSOR_Upload_Message(LORAWAN_USER_APP_CTRL_REPLY_PORT, 4, "RFAC"); + } + if ((rfac_timer > (STS_BURN_IN_RFAC + 2))) + { + APP_LOG(TS_OFF, VLEVEL_H, "\r\n -------------------Verify RFAC Success or Not\r\n"); + sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0; + if (sts_service_mask == STS_SERVICE_MASK_L2) { + sts_ac_code[0] = 0x0; + } + } + } + +} \ No newline at end of file