L14-Click 1.0
STM32WLE5CC LoRaWAN Sensor Platform
Loading...
Searching...
No Matches
mymems.c
Go to the documentation of this file.
1/*
2 * mymems.c
3 *
4 * Created on: 22. 1. 2026
5 * Author: Milan
6 */
7
8#include "mymems.h"
9#include "main.h"
10#include "flash_at25.h"
11#include "spi.h"
12#include "rtc.h"
13#include "mysensors_base.h"
14#include "mysensors.h"
15#include "nfc.h"
16#include "sys_app.h"
17#include "adc_if.h"
18#include <string.h>
19
20#define MEMS_SIGN "MTK0001" // sign of main block - version increment
21#define MEMS_SIGN_BLOCK "TM" // sign of data block
22#define MEMS_MAINBLOCK_ADDR 0
23#define MEMS_DATA_BITS_BOUNDARY 5 // Bounder data 5-32, 6-64, 7-128, 8-256
24
25#define INX_GET(nInx, nMax) (((nInx)>=0)?((nInx)%(nMax)):((nMax)-((-(nInx))%(nMax)))) // circular queue
26
28
30 { .CSPort = SPI1_CS_GPIO_Port, .CSPin = SPI1_CS_Pin, .Spi = &hspi1, .Is = 0, .Size = 0 }; // spi setting
31
32static mems_DataBlock_t _memsDataBlock = {}; // work buffer
33
34static void mens_MainBlockInit()
35{
36 memset(&_memsMainBlock, 0, sizeof(_memsMainBlock));
37 strcpy(_memsMainBlock.Sign, MEMS_SIGN);
38 // data setting
39 _memsMainBlock.Data_AddrBase = MEMS_MAINBLOCK_ADDR + sizeof(mems_MainBlock_t);
40
41 // round to 256 boundery
43 _memsMainBlock.Data_AddrBase = (1 << MEMS_DATA_BITS_BOUNDARY) + (_memsMainBlock.Data_AddrBase << MEMS_DATA_BITS_BOUNDARY);
44 _memsMainBlock.Data_Offset = 0;
45 _memsMainBlock.Data_CountMax = ((AT25_MEMSIZE / 2) - _memsMainBlock.Data_AddrBase) / sizeof(mems_DataBlock_t); // only half
46 _memsMainBlock.Data_ItemSize = sizeof(mems_DataBlock_t);
47 _memsMainBlock.Data_CountCurrent = 0;
48}
49
50/////////////////////////// public /////////////////////////
51
53{
54 HAL_StatusTypeDef status;
55 int sz = sizeof(mems_MainBlock_t);
56
57 if (sz != SZ_MAINBLOCK)
58 {
59 writeLog("The sizeof _memMainBlock:%d, expected:%d", sizeof(mems_MainBlock_t), SZ_MAINBLOCK);
61 }
62
63 sz = sizeof(mems_DataBlock_t);
64 if (sz != SZ_DATABLOCK)
65 {
66 writeLog("The sizeof mems_DataBlock_t:%d, expected:%d", sizeof(mems_DataBlock_t), SZ_DATABLOCK);
68 }
69
70 // check the senzor data size !!! never exceed 256 - otherwise the type and code must be changed
71 if (SZ_DATABLOCK >= 256)
72 {
73 writeLog("The sizeof data is greate-equal to 256, size:%d", SZ_DATABLOCK);
75 }
76
77 status = flash_at25_Init(&_flash);
78 writeLog("flash12 data: Init %s", (status == HAL_OK) ? "OK" : "failed");
79 if (status == HAL_OK)
80 {
82 if (_flash.Size < _memsMainBlock.Data_CountCurrent * _memsMainBlock.Data_ItemSize)
83 {
84 writeLog("The _flash.Size(%ud) < _memMainBlock.DataSize(%ud)", _flash.Size, _memsMainBlock.Data_CountCurrent * _memsMainBlock.Data_ItemSize);
86 }
87
88 status = mems_ReadMainBlock();
89 writeLog("flash12 data: MainBlock %s", (status == HAL_OK) ? "OK" : "failed");
90 }
91}
92
93HAL_StatusTypeDef mems_ReadMainBlock()
94{
95 HAL_StatusTypeDef status;
96
97 mens_MainBlockInit(); // initialization
99 if (status == HAL_OK)
100 {
101 //_memsMainBlock.Sign[0]='x';
102 // check of sign
103 if (_memsMainBlock.Data_CountCurrent > _memsMainBlock.Data_CountMax)
104 _memsMainBlock.Data_CountCurrent = _memsMainBlock.Data_CountMax;
105 if (strcmp(_memsMainBlock.Sign, MEMS_SIGN) != 0 || _memsMainBlock.Data_ItemSize != sizeof(mems_DataBlock_t))
106 {
107 mens_MainBlockInit(); // initialization
108 status = mems_WriteMainBlock();
109 writeLog("data: MainBlock default write %s", (status == HAL_OK) ? "OK" : "failed");
110 }
111 else
112 mems_Check(1);
113 }
114 return status;
115}
116
117HAL_StatusTypeDef mems_WriteMainBlock()
118{
119 HAL_StatusTypeDef status;
120
122 return status;
123}
124
125HAL_StatusTypeDef mems_Reset()
126{
127 HAL_StatusTypeDef status;
128 const char buf[] = "XXXX";
129
130 status = flash_at25_Write(&_flash, MEMS_MAINBLOCK_ADDR, buf, sizeof(buf));
131 return status;
132}
133
134/**
135 * @brief move the offset in circular queue
136 */
137static uint32_t mems_SetOffset(uint32_t offset, int16_t count)
138{
139#ifdef DEBUG
140 if ((offset % _memsMainBlock.Data_ItemSize) != 0)
141 {
142 writeLog("mems_MoveAddr: module is not 0!");
144 }
145#endif
146 int32_t inx = offset / _memsMainBlock.Data_ItemSize;
147
148 inx += count;
149 inx = INX_GET(inx, _memsMainBlock.Data_CountMax);
150 offset = inx * _memsMainBlock.Data_ItemSize;
151 return offset;
152}
153
154static uint32_t mems_GetAddr(uint32_t offset)
155{
156 return _memsMainBlock.Data_AddrBase + offset;
157}
158
159
161{
162 memset(&_memsDataBlock, 0, sizeof(_memsDataBlock));
163 strcpy(_memsDataBlock.Sign, MEMS_SIGN_BLOCK);
164 _memsDataBlock.Type = type;
165 return &_memsDataBlock;
166}
167
168HAL_StatusTypeDef mems_AddData(const void *data, mems_DataType_t type, uint8_t size)
169{
170 HAL_StatusTypeDef status = HAL_ERROR;
171
172 if (size < _memsMainBlock.Data_ItemSize)
173 {
174 if (data != NULL)
175 {
176 mems_InicBuffer(type);
177 _memsDataBlock.Size = size;
178 memcpy(_memsDataBlock.Data, data, size);
179 }
180 do
181 {
182 if ((status = flash_at25_Write(&_flash, mems_GetAddr(_memsMainBlock.Data_Offset), &_memsDataBlock, sizeof(_memsDataBlock))) != HAL_OK)
183 break;
184 _memsMainBlock.Data_Offset = mems_SetOffset(_memsMainBlock.Data_Offset, 1);
185 if (_memsMainBlock.Data_CountCurrent < _memsMainBlock.Data_CountMax)
186 _memsMainBlock.Data_CountCurrent++;
187 if ((status = mems_WriteMainBlock()) != HAL_OK)
188 break;
189 } while (0);
190 }
191 return status;
192}
193
194HAL_StatusTypeDef mems_GetLastData(mems_DataBlock_t **memBlock, uint8_t inxFromEnd)
195{
196 HAL_StatusTypeDef status = HAL_BUSY;
197
198 if (_memsMainBlock.Data_CountCurrent > inxFromEnd)
199 {
200 uint32_t offset = mems_SetOffset(_memsMainBlock.Data_Offset, -1 - inxFromEnd);
201
202 status = HAL_OK;
203
204 if (memBlock != NULL)
205 if ((status = flash_at25_Read(&_flash, mems_GetAddr(offset), &_memsDataBlock, sizeof(_memsDataBlock))) == HAL_OK)
206 {
207 *memBlock = &_memsDataBlock;
208 }
209 }
210 return status;
211}
212
213HAL_StatusTypeDef mems_Check(int8_t correct)
214{
215 HAL_StatusTypeDef status = HAL_OK;
216 uint16_t i;
217
218 uint32_t offset = (_memsMainBlock.Data_CountCurrent < _memsMainBlock.Data_CountMax) ? 0 : _memsMainBlock.Data_Offset;
219 for (i = 0; i < _memsMainBlock.Data_CountCurrent && HAL_OK == status; i++)
220 {
221 if ((status = flash_at25_Read(&_flash, mems_GetAddr(offset), &_memsDataBlock, sizeof(_memsDataBlock))) == HAL_OK)
222 {
223 if (strcmp(_memsDataBlock.Sign, MEMS_SIGN_BLOCK) != 0)
224 {
225 writeLog("mems_Check: failed, the sign:%s", _memsDataBlock.Sign);
226 if (correct)
227 {
228 writeLog("mems reset");
231 status = HAL_ERROR;
232 break;
233 }
235 }
236 offset = mems_SetOffset(offset, 1);
237 }
238 }
239 return status;
240}
241
242void mems_RemoveLastData(uint8_t fromEndTo)
243{
244 if (_memsMainBlock.Data_CountCurrent > 0)
245 {
246 if (_memsMainBlock.Data_CountCurrent > fromEndTo)
247 {
248 int16_t count = fromEndTo + 1;
249 _memsMainBlock.Data_CountCurrent -= count;
250 _memsMainBlock.Data_Offset = mems_SetOffset(_memsMainBlock.Data_Offset, -count);
251 }
252 else
253 {
254 _memsMainBlock.Data_CountCurrent = 0;
255 _memsMainBlock.Data_Offset = 0;
256 }
258 }
259}
260
261/**
262 * .MaxSensorData = 0, // will be updated later, according to memory chip
263 .CurrentCountSensorData = 0, // will be updated later, according to memory chip
264 .BatteryLevelStatus = 0, // will be updated later
265 .BatteryMV = 0, // will be updated later, according to memory chip
266 *
267 */
269{
270 uint8_t changes = 0;
271 uint8_t batLevel = GetBatteryLevel();
272 uint16_t batMV = SYS_GetBatteryLevel();
273
274 if (_systemParams.MemsMaxSensorData != _memsMainBlock.Data_CountMax)
275 {
276 ++changes;
277 _systemParams.MemsMaxSensorData = _memsMainBlock.Data_CountMax;
278 }
279 if (_systemParams.MemsCurrentCountSensorData != _memsMainBlock.Data_CountCurrent)
280 {
281 ++changes;
282 _systemParams.MemsCurrentCountSensorData = _memsMainBlock.Data_CountCurrent;
283 }
284 if (_systemParams.HWBatteryLevelStatus != batLevel)
285 {
286 ++changes;
287 _systemParams.HWBatteryLevelStatus = batLevel;
288 }
289 if (_systemParams.HWBatteryMV != batMV)
290 {
291 ++changes;
292 _systemParams.HWBatteryMV = batMV;
293 }
294 return changes;
295}
296
297
298///////////////////////////////////////////////////////////////////////////////////////
299// NFC
300///////////////////////////////////////////////////////////////////////////////////////
301
302
303void nfc_st25r3_OnMailboxData(uint8_t *data, uint16_t len)
304{
305// int stop=0;
306// writeLog("mam data");
307// this doesn't work, MailBox just doesn't work, giving up on it.....
308}
309
310/*
311 static void nfc_writeBattery(uint16_t addr)
312 {
313 uint8_t batCurrent = GetBatteryLevel(), batIn = 0;
314
315 HAL_StatusTypeDef status = nfc4_ReadEEPROM(_hi2c, addr, &batIn, sizeof(batIn));
316
317 if (status == HAL_OK)
318 {
319 if (batIn != batCurrent)
320 nfc4_WriteEEPROM(_hi2c, addr, &batCurrent, sizeof(batCurrent));
321 }
322 }
323 */
324
325/**
326 * @brief Read a value from an RTC backup register
327 *
328 * This function reads a 32-bit value from one of the RTC backup registers.
329 * These registers are retained during system standby mode and after system reset
330 * (as long as VDD is maintained or VBAT is supplied).
331 *
332 * @param backupRegister Backup register index (0-19 for STM32WL).
333 * Should use RTC_BKP_DRx constants defined in stm32wlxx_hal_rtc_ex.h
334 * (e.g., RTC_BKP_DR0=0, RTC_BKP_DR1=1, ..., RTC_BKP_DR19=19)
335 * @return uint32_t The 32-bit value stored in the backup register
336 */
337uint32_t getBackUpRegister(uint32_t backupRegister)
338{
339 return HAL_RTCEx_BKUPRead(&hrtc, backupRegister);
340}
341
342/**
343 * @brief Write a value to an RTC backup register
344 *
345 * This function writes a 32-bit value to one of the RTC backup registers.
346 * These registers are retained during system standby mode and after system reset
347 * (as long as VDD is maintained or VBAT is supplied).
348 *
349 * Use this function to save critical data before entering standby mode.
350 * On restart, read the values using getBackUpRegister() to check system state
351 * and restore necessary information.
352 *
353 * @param backupRegister Backup register index (0-19 for STM32WL).
354 * Should use RTC_BKP_DRx constants defined in stm32wlxx_hal_rtc_ex.h
355 * (e.g., RTC_BKP_DR0=0, RTC_BKP_DR1=1, ..., RTC_BKP_DR19=19)
356 * @param value The 32-bit value to store in the backup register
357 */
358void setBackUpRegister(uint32_t backupRegister, uint32_t value)
359{
360 HAL_PWR_EnableBkUpAccess();
361 HAL_RTCEx_BKUPWrite(&hrtc, backupRegister, value);
362 HAL_PWR_DisableBkUpAccess();
363}
364
Header for ADC interface configuration.
uint16_t SYS_GetBatteryLevel(void)
Get the current battery level.
Definition adc_if.c:139
HAL_StatusTypeDef flash_at25_Read(const flash_at25CS_t *s, uint32_t addr, void *buffer, uint16_t size)
Fast read from flash memory Uses fast read command (0x0B) for improved performance in frequent read o...
Definition flash_at25.c:140
HAL_StatusTypeDef flash_at25_Write(const flash_at25CS_t *s, uint32_t addr, const void *data, uint16_t size)
Write to flash memory with sector preservation Handles page-aligned writes efficiently with proper ve...
Definition flash_at25.c:229
HAL_StatusTypeDef flash_at25_Init(flash_at25CS_t *s)
Initialization for AT25EU0041A flash chip Performs proper device identification and verification Suit...
Definition flash_at25.c:98
#define AT25_MEMSIZE
Definition flash_at25.h:24
: Header for main.c file. This file contains the common defines of the application.
void Error_Handler(void)
Default error handler called by HAL on unrecoverable errors. Disables interrupts and enters an infini...
Definition main.c:505
void writeLog(const char *format,...)
Format and send a log message over UART (printf-style). Available only when WRITELOG is defined; comp...
Definition main.c:97
#define SPI1_CS_Pin
Definition main.h:142
#define SPI1_CS_GPIO_Port
Definition main.h:143
void mems_RemoveLastData(uint8_t fromEndTo)
remove last data
Definition mymems.c:242
HAL_StatusTypeDef mems_GetLastData(mems_DataBlock_t **memBlock, uint8_t inxFromEnd)
Get the last sensor data if exists. The data and mem block is stored in work buffer,...
Definition mymems.c:194
static flash_at25CS_t _flash
Definition mymems.c:29
uint8_t mems_WriteToSystemParams()
write data from memory to systemParams
Definition mymems.c:268
#define MEMS_DATA_BITS_BOUNDARY
Definition mymems.c:23
void mems_Init()
Initialise NFC and external flash; load the main block and system parameters. Verifies the flash sign...
Definition mymems.c:52
static void mens_MainBlockInit()
Definition mymems.c:34
HAL_StatusTypeDef mems_AddData(const void *data, mems_DataType_t type, uint8_t size)
write new data of sensor at the end of queue, if is no space, the most older data start to rewrites
Definition mymems.c:168
mems_DataBlock_t * mems_InicBuffer(mems_DataType_t type)
Initialize the work buffer - _memsDataBlock.
Definition mymems.c:160
HAL_StatusTypeDef mems_Reset()
memory reset - remove sign from chip
Definition mymems.c:125
void setBackUpRegister(uint32_t backupRegister, uint32_t value)
Write a value to an RTC backup register.
Definition mymems.c:358
#define MEMS_MAINBLOCK_ADDR
Definition mymems.c:22
static mems_DataBlock_t _memsDataBlock
Definition mymems.c:32
#define INX_GET(nInx, nMax)
Definition mymems.c:25
#define MEMS_SIGN
Definition mymems.c:20
HAL_StatusTypeDef mems_WriteMainBlock()
writing the main block on flash. The main block is stored on address 0
Definition mymems.c:117
#define MEMS_SIGN_BLOCK
Definition mymems.c:21
void nfc_st25r3_OnMailboxData(uint8_t *data, uint16_t len)
Definition mymems.c:303
static uint32_t mems_SetOffset(uint32_t offset, int16_t count)
move the offset in circular queue
Definition mymems.c:137
static uint32_t mems_GetAddr(uint32_t offset)
Definition mymems.c:154
uint32_t getBackUpRegister(uint32_t backupRegister)
Read a value from an RTC backup register.
Definition mymems.c:337
HAL_StatusTypeDef mems_Check(int8_t correct)
Check the memory consist.
Definition mymems.c:213
HAL_StatusTypeDef mems_ReadMainBlock()
reading of main block from flash. If there is not valid MEMS_SIGN, the structure is initialize to 0 T...
Definition mymems.c:93
#define SZ_MAINBLOCK
Size in bytes of the mems_MainBlock_t structure written at flash address 0.
Definition mymems.h:20
#define SZ_DATABLOCK
Size in bytes of one mems_DataBlock_t entry in the circular data queue. Equals 5 bytes of header plus...
Definition mymems.h:28
mems_MainBlock_t _memsMainBlock
Global instance of the main flash control block; loaded by mems_ReadMainBlock().
Definition mymems.c:27
mems_DataType_t
Type tag stored in each mems_DataBlock_t to identify the payload format. Used when reading back block...
Definition mymems.h:65
systemParams_t _systemParams
This file contains all the function prototypes for the rtc.c file.
RTC_HandleTypeDef hrtc
Definition rtc.c:27
This file contains all the function prototypes for the spi.c file.
SPI_HandleTypeDef hspi1
Definition spi.c:27
Configuration and state descriptor for one AT25EU0041A flash chip. Pass a pointer to this struct to e...
Definition flash_at25.h:34
Sensor data record stored as one element in the flash circular queue.
Definition mymems.h:78
Master control block stored at flash address 0.
Definition mymems.h:42
Function prototypes for sys_app.c file.
uint8_t GetBatteryLevel(void)
callback to get the battery level in % of full charge (254 full charge, 0 no charge)
Definition sys_app.c:152