From 47d6313ba1d9c177814651c656afceddde73fab0 Mon Sep 17 00:00:00 2001 From: Winfred LIN Date: Fri, 3 Apr 2020 18:21:16 +1100 Subject: [PATCH] added reading flash functions for stm32l0xx series 1. implemented HAL_StatusTypeDef HAL_FLASH_ReadWord(uint32_t Address, uint32_t* Data); and HAL_StatusTypeDef HAL_FLASH_ReadHalfWord(uint32_t Address, uint16_t* Data); which allows user to read the internal FLASH (with out read protection) 2. implemeted device_config struct to store device configurations, e.g. magnetometer fullscale, report period, etc. 3. added demonstration code of using flash reading apis in lora_demo.c, in which the configuration sent from the cloud is stored into the internal Data EEPROM bank1, and each time when the device is booted, the configurations would be loaded from the Data EEPROM and used to initialize the application. --- .../BSP/HardWare/Common/bsp.c | 5 +- .../BSP/HardWare/Common/bsp.h | 54 +++---- board/NUCLEO_STM32L073RZ/BSP/Src/lora_demo.c | 149 ++++++++++++++++-- .../IAR/lorawan/TencentOS_tiny.ewp | 15 +- .../IAR/lorawan/TencentOS_tiny.ewt | 15 +- examples/LoRaWAN/lora_demo.h | 7 +- .../Inc/stm32l0xx_hal_flash_ex2.h | 43 +++++ .../Src/stm32l0xx_hal_flash_ex2.c | 89 +++++++++++ 8 files changed, 313 insertions(+), 64 deletions(-) create mode 100644 platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_flash_ex2.h create mode 100644 platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex2.c diff --git a/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.c b/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.c index 57f6df9c..facb7837 100644 --- a/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.c +++ b/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.c @@ -3,19 +3,20 @@ * @file bsp.c * @author jieranzhi * @brief provide high level interfaces to manage the sensors on the - * application, this is a modified version of the official api + * application ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "bsp.h" -void BSP_Sensor_Init(void) +void BSP_Sensor_Init(DeviceConfig_TypeDef config) { /* Initialize sensors */ HTS221_Init(); LPS22HB_Init(); LIS3MDL_Init(); + LIS3MDL_Set_FullScale((LIS3MDL_FullScaleTypeDef)config.magn_fullscale); } void BSP_Sensor_Read(sensor_data_t *sensor_data) diff --git a/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.h b/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.h index c9f515ae..6ed73014 100644 --- a/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.h +++ b/board/NUCLEO_STM32L073RZ/BSP/HardWare/Common/bsp.h @@ -1,33 +1,9 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - (C)2013 Semtech - -Description: contains all hardware driver - -License: Revised BSD License, see LICENSE.TXT file include in the project - -Maintainer: Miguel Luis and Gregory Cristian -*/ /** ****************************************************************************** - * @file bsp.h - * @author MCD Application Team - * @brief contains all hardware driver - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2018 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * + * @file bsp.c + * @author jieranzhi + * @brief provide high level interfaces to manage the sensors on the + * application, this is a modified version of the official api ****************************************************************************** */ @@ -40,6 +16,7 @@ extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include +#include #include "HTS221.h" #include "LPS22HB.h" #include "LIS3MDL.h" @@ -61,6 +38,25 @@ typedef struct } sensor_data_t; + // application configuration types + typedef enum{ + DCT_IS_CONFIRM = 0x00U, + DCT_REPORT_PERIOD = 0x01U, + DCT_REPEAT_TIME = 0x02U, + DCT_MAGN_FULLSCALE = 0x03U, + DCT_DEFAULT = 0xFFU, + }DeviceConfigType_TypeDef; + +// application configuration +typedef struct +{ + uint32_t config_address; + uint16_t report_period; + uint8_t repeat_time; + LIS3MDL_FullScaleTypeDef magn_fullscale; + bool is_confirmed; +}DeviceConfig_TypeDef; + /* Exported constants --------------------------------------------------------*/ /* External variables --------------------------------------------------------*/ /* Exported macros -----------------------------------------------------------*/ @@ -71,7 +67,7 @@ typedef struct * @note * @retval None */ -void BSP_Sensor_Init(void); +void BSP_Sensor_Init(DeviceConfig_TypeDef config); /** * @brief sensor read. diff --git a/board/NUCLEO_STM32L073RZ/BSP/Src/lora_demo.c b/board/NUCLEO_STM32L073RZ/BSP/Src/lora_demo.c index 35583663..76d00d1a 100644 --- a/board/NUCLEO_STM32L073RZ/BSP/Src/lora_demo.c +++ b/board/NUCLEO_STM32L073RZ/BSP/Src/lora_demo.c @@ -1,7 +1,7 @@ #include "lora_demo.h" +#include "stm32l0xx_hal_flash_ex2.h" #include "RHF76.h" #include "bsp.h" -#include #include /* @@ -118,9 +118,6 @@ */ -uint16_t report_period = 10; -bool is_confirmed = true; - typedef struct device_data_st { uint8_t magn_fullscale; // fullscale of magnetometer(RW) uint8_t temp_sensitivity; // temperature sensitivity (R) @@ -145,6 +142,118 @@ typedef struct device_data_wrapper_st { dev_data_wrapper_t dev_data_wrapper; +DeviceConfig_TypeDef device_config; + +void set_config_to_default(DeviceConfig_TypeDef* config) +{ + config->config_address = 0x08080000U; + config->is_confirmed = true; + config->report_period = 10; + config->magn_fullscale = FULLSCALE_4; +} + +/** + * @brief Write the configuration to the internal EEPROM bank 1 + * @note a single config frame is of 32-bit(a word, 4bytes), and the config + * block starts with a frame whose value is 0x464E4F43U ('CONF' from + * low to high) and ends with a frame with a value of 0xFFFFFFFFU; a + * single data frame has a following structure£º + * ---------------------------------------------------------------- + * | byte | 0 | 1 | 2 | 3 | + * ---------------------------------------------------------------- + * | value| Device Config Type | value-L | value-H | reserve | + * ---------------------------------------------------------------- + * the reserve byte could be used as an extra byte for the config + * value, i.e. a 24-bit value. + * + * @param config system configurations + * + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef write_config_to_Flash(DeviceConfig_TypeDef config) +{ + uint32_t frame[5] = {0}; + frame[0] = 0x464E4F43U; // <'C'><'O'><'N'><'F'> from low to high + frame[1] = (uint32_t)config.is_confirmed<<8 | (uint32_t)DCT_IS_CONFIRM; + frame[2] = (uint32_t)config.report_period<<8 | (uint32_t)DCT_REPORT_PERIOD; + frame[3] = (uint32_t)config.repeat_time<<8 | (uint32_t)DCT_REPEAT_TIME; + frame[4] = 0xFFFFFFFFU; + + HAL_FLASH_Unlock(); + uint8_t retry = 10; + + HAL_StatusTypeDef status = HAL_OK; + for(int i=0; i<5; i++) + { + status = HAL_OK; + do{ + status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, config.config_address+4*i, frame[i]); + }while(retry--!=0 && status != HAL_OK); + } + HAL_FLASH_Lock(); + + return status; +} + +HAL_StatusTypeDef read_config_from_Flash(DeviceConfig_TypeDef* config) +{ + uint32_t data = 0; + HAL_StatusTypeDef status = HAL_FLASH_ReadWord(config->config_address, &data); + if(status == HAL_OK) + { + // a valid config starts with <'C'><'O'><'N'><'F'> and ended with a word of 0xFFFFFFFF + if((char)(data&0xFF) == 'C' + &&(char)(data>>8&0xFF) == 'O' + &&(char)(data>>16&0xFF) == 'N' + &&(char)(data>>24&0xFF) == 'F') + { + int i = 0; + int retry = 10; + DeviceConfigType_TypeDef config_type = DCT_DEFAULT; + while(data!=0xFFFFFFFF) + { + i+=4; + status = HAL_FLASH_ReadWord(config->config_address+i, &data); + if(status != HAL_OK){ + retry--; + i-=4; + if(retry == 0) break; + }else{ + config_type = (DeviceConfigType_TypeDef)(data&0xFF); + switch(config_type) + { + case DCT_IS_CONFIRM: + { + config->is_confirmed = (bool)(data>>8&0xFF); + break; + } + case DCT_REPORT_PERIOD: + { + config->report_period = (uint16_t)(data>>8&0xFFFF); + break; + } + case DCT_REPEAT_TIME: + { + config->repeat_time = (uint8_t)(data>>8&0xFF); + break; + } + case DCT_MAGN_FULLSCALE: + { + config->magn_fullscale = (LIS3MDL_FullScaleTypeDef)(data>>8&0xFF); + break; + } + default: + { + break; + } + } + } + } + } + } + return status; +} + void recv_callback(uint8_t *data, uint8_t len) { printf("len: %d\n", len); @@ -154,11 +263,13 @@ void recv_callback(uint8_t *data, uint8_t len) } if (len == 1) { - report_period = data[0]; + device_config.report_period = data[0]; } else if (len >= 2) { - report_period = data[0] | (data[1] << 8); - LIS3MDL_Set_FullScale((LIS3MDL_FullScaleTypeDef)data[2]); - is_confirmed = (bool)data[3]; + device_config.is_confirmed = (bool)data[3]; + device_config.report_period = data[0] | (data[1] << 8); + device_config.magn_fullscale = (LIS3MDL_FullScaleTypeDef)data[2]; + LIS3MDL_Set_FullScale(device_config.magn_fullscale); + write_config_to_Flash(device_config); } } @@ -181,15 +292,22 @@ void print_to_screen(sensor_data_t sensor_data) */ void application_entry(void *arg) { + // retrieve configuration from the EEPROM (if any) + set_config_to_default(&device_config); + HAL_StatusTypeDef status = read_config_from_Flash(&device_config); + if(status != HAL_OK) + { + printf("retrieve configuration FAILED!\r\n"); + } + + // initialization sensor_data_t sensor_data; - - // initialization of sensors - BSP_Sensor_Init(); - + BSP_Sensor_Init(device_config); rhf76_lora_init(HAL_UART_PORT_1); tos_lora_module_recvcb_register(recv_callback); tos_lora_module_join_otaa("8cf957200000f52c", "8cf957200000f52c6d09aaaaad204a72"); + // do the job while (1) { BSP_Sensor_Read(&sensor_data); print_to_screen(sensor_data); @@ -205,15 +323,14 @@ void application_entry(void *arg) dev_data_wrapper.u.dev_data.magn_y = (int16_t)(sensor_data.sensor_magn.magn_y); dev_data_wrapper.u.dev_data.magn_z = (int16_t)(sensor_data.sensor_magn.magn_z); dev_data_wrapper.u.dev_data.pressure = (uint32_t)(sensor_data.sensor_press.pressure); - dev_data_wrapper.u.dev_data.period = report_period; + dev_data_wrapper.u.dev_data.period = device_config.report_period; // send data to the server (via gateway) - if(is_confirmed){ + if(device_config.is_confirmed){ tos_lora_module_send(dev_data_wrapper.u.serialize, sizeof(dev_data_t)); }else{ tos_lora_module_send_unconfirmed(dev_data_wrapper.u.serialize, sizeof(dev_data_t)); } - - tos_task_delay(report_period * 1000); + tos_task_delay(device_config.report_period * 1000); } } diff --git a/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewp b/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewp index ce06297d..84a1b288 100644 --- a/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewp +++ b/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewp @@ -1123,14 +1123,14 @@ $PROJ_DIR$\..\..\..\..\devices\rhf76_lora\RHF76.c - - Drivers/CMSIS - - $PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c - - Drivers/STM32L0xx_HAL_Driver + + Drivers/CMSIS + + $PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c + + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal.c @@ -1146,6 +1146,9 @@ $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex.c + + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex2.c + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ramfunc.c diff --git a/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewt b/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewt index 4267415e..b3317fc0 100644 --- a/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewt +++ b/board/NUCLEO_STM32L073RZ/IAR/lorawan/TencentOS_tiny.ewt @@ -1257,14 +1257,14 @@ $PROJ_DIR$\..\..\..\..\devices\rhf76_lora\RHF76.c - - Drivers/CMSIS - - $PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c - - Drivers/STM32L0xx_HAL_Driver + + Drivers/CMSIS + + $PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c + + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal.c @@ -1280,6 +1280,9 @@ $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex.c + + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex2.c + $PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ramfunc.c diff --git a/examples/LoRaWAN/lora_demo.h b/examples/LoRaWAN/lora_demo.h index f6222c8e..9455bd6a 100644 --- a/examples/LoRaWAN/lora_demo.h +++ b/examples/LoRaWAN/lora_demo.h @@ -1,20 +1,17 @@ #ifndef __APP_DEMO_H__ #define __APP_DEMO_H__ +#include #include "mcu_init.h" #include "tos_at.h" #include "string.h" #include "cmsis_os.h" #include "lora_module_wrapper.h" + #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - char data[32]; -}ReportData_TypeDef; - void application_entry(void *arg); #ifdef __cplusplus } diff --git a/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_flash_ex2.h b/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_flash_ex2.h new file mode 100644 index 00000000..9641f2a8 --- /dev/null +++ b/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Inc/stm32l0xx_hal_flash_ex2.h @@ -0,0 +1,43 @@ +/** + ****************************************************************************** + * @file stm32l0xx_hal_flash_ex2.h + * @author jieranzhi + * @date 2020/04/02 14:59 CST + * @brief Header file of Flash EEPROM. + ****************************************************************************** + * @attention + * + * this file implementes FLASH read operations for stm32l0xx series(category 5 + * devices), to implement a morefunctions, please refer to RM0367, which could + * be downloaded from: + * https://www.st.com/resource/en/reference_manual/dm00095744-ultra-low-power- + * stm32l0x3-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L0xx_HAL_FLASH_EX2_H +#define __STM32L0xx_HAL_FLASH_EX2_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l0xx_hal.h" + +/* Include FLASH HAL Extended module */ +#include "stm32l0xx_hal_flash_ex.h" +#include "stm32l0xx_hal_flash_ramfunc.h" + +/* Exported functions --------------------------------------------------------*/ +void HAL_FLASH_Prepare_Reading(uint8_t WaitState); +HAL_StatusTypeDef HAL_FLASH_ReadWord(uint32_t Address, uint32_t* Data); +HAL_StatusTypeDef HAL_FLASH_ReadHalfWord(uint32_t Address, uint16_t* Data); + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L0xx_HAL_FLASH_EX2_H */ \ No newline at end of file diff --git a/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex2.c b/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex2.c new file mode 100644 index 00000000..2a341d3d --- /dev/null +++ b/platform/vendor_bsp/st/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex2.c @@ -0,0 +1,89 @@ +/** + ****************************************************************************** + * @file stm32l0xx_hal_flash_eeprom.c + * @author jieranzhi + * @date 2020/04/02 14:59 CST + * @brief implementation of Flash EEPROM operations. + ****************************************************************************** + * @attention + * + * this file implementes FLASH read operations for stm32l0xx series(category 5 + * devices), to implement a morefunctions, please refer to RM0367, which could + * be downloaded from: + * https://www.st.com/resource/en/reference_manual/dm00095744-ultra-low-power- + * stm32l0x3-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf + ****************************************************************************** + */ + +#include "stm32l0xx_hal_flash_ex2.h" + +/** + * @brief set the correct number of wait states, and set the clock of the memory + interface + * @note The user must set the correct number of wait states (LATENCY bit in + * the FLASH_ACR register). No control is done to verify if the frequency + * or the power used is correct, with respect to the number of wait + * states. A wrong number of wait states can generate wrong read values + * (high frequency and 0 wait states) or a long time to execute a code + * (low frequency with 1 wait state). + * @param correct number of wait states + */ +void HAL_FLASH_Prepare_Reading(uint8_t WaitState) +{ + __HAL_RCC_MIF_CLK_ENABLE(); + __HAL_FLASH_SET_LATENCY(WaitState); +} + +/** + * @brief Read word (4 bytes) from a specified address + * @note To correctly run this function, the HAL_FLASH_Prepare_Reading(...) + * function must be called before. + * + * @param Address Specifie the address to be read from. + * @param Data Specifie the data to store the + * + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_ReadWord(uint32_t Address, uint32_t* Data) +{ + HAL_StatusTypeDef status = HAL_ERROR; + + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)||IS_FLASH_DATA_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + *Data = *(__IO uint32_t*)Address; + } + return status; +} + +/** + * @brief Read half-word (2 bytes) from a specified address + * @note To correctly run this function, the HAL_FLASH_Prepare_Reading(...) + * function must be called before. + * + * @param Address Specifie the address to be read from. + * @param Data Specifie the data to store the + * + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_ReadHalfWord(uint32_t Address, uint16_t* Data) +{ + HAL_StatusTypeDef status = HAL_ERROR; + + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)||IS_FLASH_DATA_ADDRESS(Address)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + *Data = *(__IO uint16_t*)Address; + } + return status; +} \ No newline at end of file