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.
This commit is contained in:
Winfred LIN
2020-04-03 18:21:16 +11:00
parent cafe9c8a87
commit 47d6313ba1
8 changed files with 313 additions and 64 deletions

View File

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

View File

@@ -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
*
* <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
* All rights reserved.</center></h2>
*
* 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 <stdint.h>
#include <stdbool.h>
#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.

View File

@@ -1,7 +1,7 @@
#include "lora_demo.h"
#include "stm32l0xx_hal_flash_ex2.h"
#include "RHF76.h"
#include "bsp.h"
#include <stdbool.h>
#include <Math.h>
/*
@@ -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<72><65>
* ----------------------------------------------------------------
* | 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);
}
}

View File

@@ -1123,14 +1123,14 @@
<name>$PROJ_DIR$\..\..\..\..\devices\rhf76_lora\RHF76.c</name>
</file>
</group>
<group>
<name>Drivers/CMSIS</name>
<file>
<name>$PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c</name>
</file>
</group>
<group>
<name>Drivers/STM32L0xx_HAL_Driver</name>
<group>
<name>Drivers/CMSIS</name>
<file>
<name>$PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c</name>
</file>
</group>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal.c</name>
</file>
@@ -1146,6 +1146,9 @@
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex2.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ramfunc.c</name>
</file>

View File

@@ -1257,14 +1257,14 @@
<name>$PROJ_DIR$\..\..\..\..\devices\rhf76_lora\RHF76.c</name>
</file>
</group>
<group>
<name>Drivers/CMSIS</name>
<file>
<name>$PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c</name>
</file>
</group>
<group>
<name>Drivers/STM32L0xx_HAL_Driver</name>
<group>
<name>Drivers/CMSIS</name>
<file>
<name>$PROJ_DIR$\..\..\BSP\Src\system_stm32l0xx.c</name>
</file>
</group>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal.c</name>
</file>
@@ -1280,6 +1280,9 @@
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ex2.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\..\..\platform\vendor_bsp\st\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_flash_ramfunc.c</name>
</file>

View File

@@ -1,20 +1,17 @@
#ifndef __APP_DEMO_H__
#define __APP_DEMO_H__
#include <stdbool.h>
#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
}

View File

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

View File

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