add hmac support

This commit is contained in:
Yunhorn 2023-10-15 20:29:36 +08:00
parent 05b42f2355
commit 96793a53df
9 changed files with 828 additions and 319 deletions

View File

@ -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 */

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#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
/**
* @}
*/
/**
* @}
*/

View File

@ -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 */

View File

@ -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 */

View File

@ -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),

51
Core/Src/cmox_low_level.c Normal file
View File

@ -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****/

View File

@ -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 */

View File

@ -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;i<sizeof(Computed_Tag_SHA1); i++) {
APP_LOG(TS_OFF,VLEVEL_M,"0x%02x ", hmac_result.hmac_tag[i]);
}
ret = memcmp(hmac_result.hmac_tag, (void *)sts_ac_code, sizeof(sts_ac_code));
if (ret !=0)
{
hmac_result.ac_pass =0U;
APP_LOG(TS_OFF, VLEVEL_M, "\r\nHMAC Verify Error \r\n");
} else
{
ret =0;
hmac_result.ac_pass = 1U;
APP_LOG(TS_OFF, VLEVEL_M, "\r\nHMAC Verify Success\r\n");
}
return ret;
}
uint32_t sts_hmac_sha1(const uint8_t *key, int key_length, const uint8_t *message, int message_length, hmac_result_t *hmac_result)
{
cmox_mac_retval_t retval=0;
size_t computed_size=0;
/* Initialize cryptographic library */
if (cmox_initialize(NULL) != CMOX_INIT_SUCCESS)
{
retval = 1;
return retval;
}
/* Compute directly the authentication tag passing all the needed parameters */
retval = cmox_mac_compute(CMOX_HMAC_SHA1_ALGO, /* Use HMAC SHA256 algorithm */
message, message_length, /* Message to authenticate */
key, key_length, /* HMAC Key to use */
NULL, 0, /* Custom data */
Computed_Tag_SHA1, /* Data buffer to receive generated authnetication tag */
sizeof(Computed_Tag_SHA1), /* Expected authentication tag size */
&computed_size); /* Generated tag size */
memcpy(hmac_result->hmac_tag, Computed_Tag_SHA1, sizeof(Computed_Tag_SHA1));
hmac_result->hmac_tag_size = computed_size;
return retval;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -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;
}
}
}
}