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 "utils/mydefs.h"
19#include "utils/utils.h"
20#include <string.h>
21
22
23#define MEMS_SIGN "MTK0001" // sign of main block - version increment
24#define MEMS_SIGN_BLOCK "TM" // sign of data block
25#define MEMS_MAINBLOCK_ADDR 0
26#define MEMS_DATA_BITS_BOUNDARY 5 // Bounder data 5-32, 6-64, 7-128, 8-256
27
28
30
32 { .CSPort = SPI1_CS_GPIO_Port, .CSPin = SPI1_CS_Pin, .Spi = &hspi1, .Is = 0, .Size = 0 }; // spi setting
33
34static mems_DataBlock_t _memsDataBlock = {}; // work buffer
35
36static void mems_SetCRC()
37{
38 _memsMainBlock.Crc = calculateCrc((uint8_t*)&_memsMainBlock, sizeof(_memsMainBlock) - sizeof(_memsMainBlock.Crc));
39}
40
41static uint8_t mems_CheckCRC()
42{
43 uint8_t crc = calculateCrc((uint8_t*)&_memsMainBlock, sizeof(_memsMainBlock) - sizeof(_memsMainBlock.Crc));
44 return crc == _memsMainBlock.Crc;
45}
46
47static void mens_MainBlockInit()
48{
49 memset(&_memsMainBlock, 0, sizeof(_memsMainBlock));
50 strcpy(_memsMainBlock.Sign, MEMS_SIGN);
51 // data setting
52 _memsMainBlock.Data_AddrBase = MEMS_MAINBLOCK_ADDR + sizeof(mems_MainBlock_t);
53
54 // round to 256 boundery
56 _memsMainBlock.Data_AddrBase = (1 << MEMS_DATA_BITS_BOUNDARY) + (_memsMainBlock.Data_AddrBase << MEMS_DATA_BITS_BOUNDARY);
57 _memsMainBlock.Data_Offset = 0;
58 _memsMainBlock.Data_CountMax = ((AT25_MEMSIZE / 2) - _memsMainBlock.Data_AddrBase) / sizeof(mems_DataBlock_t); // only half
59 _memsMainBlock.Data_ItemSize = sizeof(mems_DataBlock_t);
60 _memsMainBlock.Data_CountCurrent = 0;
62}
63
64/////////////////////////// public /////////////////////////
65
67{
68 HAL_StatusTypeDef status;
69 int sz = sizeof(mems_MainBlock_t);
70
71 if (sz != SZ_MAINBLOCK)
72 {
73 writeLog("The sizeof _memMainBlock:%d, expected:%d", sizeof(mems_MainBlock_t), SZ_MAINBLOCK);
75 }
76
77 sz = sizeof(mems_DataBlock_t);
78 if (sz != SZ_DATABLOCK)
79 {
80 writeLog("The sizeof mems_DataBlock_t:%d, expected:%d", sizeof(mems_DataBlock_t), SZ_DATABLOCK);
82 }
83
84 // check the senzor data size !!! never exceed 256 - otherwise the type and code must be changed
85 if (SZ_DATABLOCK >= 256)
86 {
87 writeLog("The sizeof data is greate-equal to 256, size:%d", SZ_DATABLOCK);
89 }
90
91 /*
92 // this is necessary, because the flash chip is controlled by 3v3 enb GPIO.
93 // I don't know why this is necessary
94 int repeat = 5;
95 do
96 {
97 status = flash_at25_Init(&_flash);
98 if (status != HAL_OK)
99 HAL_Delay(1000);
100 } while(status != HAL_OK && --repeat);
101 */
102
103 status = flash_at25_Init(&_flash);
104 writeLog("flash12 data: Init %s", (status == HAL_OK) ? "OK" : "failed");
105 if (status == HAL_OK)
106 {
108 if (_flash.Size < _memsMainBlock.Data_CountCurrent * _memsMainBlock.Data_ItemSize)
109 {
110 writeLog("The _flash.Size(%ud) < _memMainBlock.DataSize(%ud)", _flash.Size, _memsMainBlock.Data_CountCurrent * _memsMainBlock.Data_ItemSize);
112 }
113
114 status = mems_ReadMainBlock();
115 writeLog("flash12 data: MainBlock %s", (status == HAL_OK) ? "OK" : "failed");
116 }
117}
118
119HAL_StatusTypeDef mems_ReadMainBlock()
120{
121 HAL_StatusTypeDef status;
122
123 mens_MainBlockInit(); // initialization
125 if (status == HAL_OK)
126 {
127 //_memsMainBlock.Sign[0]='x';
128 // check of sign
129 _memsMainBlock.Data_CountCurrent = CLAMP(_memsMainBlock.Data_CountCurrent, 0, _memsMainBlock.Data_CountMax);
130 if (strcmp(_memsMainBlock.Sign, MEMS_SIGN) != 0 || _memsMainBlock.Data_ItemSize != sizeof(mems_DataBlock_t) || !mems_CheckCRC())
131 {
132 mens_MainBlockInit(); // initialization
133 status = mems_WriteMainBlock();
134 writeLog("data: MainBlock default write %s", (status == HAL_OK) ? "OK" : "failed");
135 }
136 else
137 mems_Check(1);
138 }
139 return status;
140}
141
142HAL_StatusTypeDef mems_WriteMainBlock()
143{
144 HAL_StatusTypeDef status = HAL_OK;
145
146 //writeLog("mems_WriteMainBlock: kokot");
147 mems_SetCRC();
149 return status;
150}
151
152HAL_StatusTypeDef mems_Reset()
153{
154 HAL_StatusTypeDef status;
155 const char buf[] = "XXXX";
156
157 status = flash_at25_Write(&_flash, MEMS_MAINBLOCK_ADDR, buf, sizeof(buf));
158 return status;
159}
160
161/**
162 * @brief move the offset in circular queue
163 */
164static uint32_t mems_SetOffset(uint32_t offset, int16_t count)
165{
166#ifdef DEBUG
167 if ((offset % _memsMainBlock.Data_ItemSize) != 0)
168 {
169 writeLog("mems_MoveAddr: module is not 0!");
171 }
172#endif
173 int32_t inx = offset / _memsMainBlock.Data_ItemSize;
174
175 inx += count;
176 inx = INX_GET(inx, _memsMainBlock.Data_CountMax);
177 offset = inx * _memsMainBlock.Data_ItemSize;
178 return offset;
179}
180
181static uint32_t mems_GetAddr(uint32_t offset)
182{
183 return _memsMainBlock.Data_AddrBase + offset;
184}
185
186
188{
189 memset(&_memsDataBlock, 0, sizeof(_memsDataBlock));
190 strcpy(_memsDataBlock.Sign, MEMS_SIGN_BLOCK);
191 _memsDataBlock.Type = type;
192 return &_memsDataBlock;
193}
194
195HAL_StatusTypeDef mems_AddData(const void *data, mems_DataType_t type, uint8_t size)
196{
197 HAL_StatusTypeDef status = HAL_ERROR;
198
199 if (size < _memsMainBlock.Data_ItemSize)
200 {
201 if (data != NULL)
202 {
203 mems_InicBuffer(type);
204 _memsDataBlock.Size = size;
205 memcpy(_memsDataBlock.Data, data, size);
206 }
207 do
208 {
209 if ((status = flash_at25_Write(&_flash, mems_GetAddr(_memsMainBlock.Data_Offset), &_memsDataBlock, sizeof(_memsDataBlock))) != HAL_OK)
210 break;
211 _memsMainBlock.Data_Offset = mems_SetOffset(_memsMainBlock.Data_Offset, 1);
212 if (_memsMainBlock.Data_CountCurrent < _memsMainBlock.Data_CountMax)
213 _memsMainBlock.Data_CountCurrent++;
214 if ((status = mems_WriteMainBlock()) != HAL_OK)
215 break;
216 } while (0);
217 }
218 return status;
219}
220
221HAL_StatusTypeDef mems_GetLastData(mems_DataBlock_t **memBlock, uint8_t inxFromEnd)
222{
223 HAL_StatusTypeDef status = HAL_BUSY;
224
225 if (_memsMainBlock.Data_CountCurrent > inxFromEnd)
226 {
227 uint32_t offset = mems_SetOffset(_memsMainBlock.Data_Offset, -1 - inxFromEnd);
228
229 status = HAL_OK;
230
231 if (memBlock != NULL)
232 if ((status = flash_at25_Read(&_flash, mems_GetAddr(offset), &_memsDataBlock, sizeof(_memsDataBlock))) == HAL_OK)
233 {
234 *memBlock = &_memsDataBlock;
235 }
236 }
237 return status;
238}
239
240HAL_StatusTypeDef mems_Check(int8_t correct)
241{
242 HAL_StatusTypeDef status = HAL_OK;
243 uint16_t i;
244
245 uint32_t offset = (_memsMainBlock.Data_CountCurrent < _memsMainBlock.Data_CountMax) ? 0 : _memsMainBlock.Data_Offset;
246 for (i = 0; i < _memsMainBlock.Data_CountCurrent && HAL_OK == status; i++)
247 {
248 if ((status = flash_at25_Read(&_flash, mems_GetAddr(offset), &_memsDataBlock, sizeof(_memsDataBlock))) == HAL_OK)
249 {
250 if (strcmp(_memsDataBlock.Sign, MEMS_SIGN_BLOCK) != 0)
251 {
252 writeLog("mems_Check: failed, the sign:%s", _memsDataBlock.Sign);
253 if (correct)
254 {
255 writeLog("mems reset");
258 status = HAL_ERROR;
259 break;
260 }
262 }
263 offset = mems_SetOffset(offset, 1);
264 }
265 }
266 return status;
267}
268
269void mems_RemoveLastData(uint8_t fromEndTo)
270{
271 if (_memsMainBlock.Data_CountCurrent > 0)
272 {
273 if (_memsMainBlock.Data_CountCurrent > fromEndTo)
274 {
275 int16_t count = fromEndTo + 1;
276 _memsMainBlock.Data_CountCurrent -= count;
277 _memsMainBlock.Data_Offset = mems_SetOffset(_memsMainBlock.Data_Offset, -count);
278 }
279 else
280 {
281 _memsMainBlock.Data_CountCurrent = 0;
282 _memsMainBlock.Data_Offset = 0;
283 }
285 }
286}
287
288/**
289 * .MaxSensorData = 0, // will be updated later, according to memory chip
290 .CurrentCountSensorData = 0, // will be updated later, according to memory chip
291 .BatteryLevelStatus = 0, // will be updated later
292 .BatteryMV = 0, // will be updated later, according to memory chip
293 *
294 */
296{
297 uint8_t changes = 0;
298 uint8_t batLevel = GetBatteryLevel();
299 uint16_t batMV = SYS_GetBatteryLevel();
300
301 if (_systemParams.MemsMaxSensorData != _memsMainBlock.Data_CountMax)
302 {
303 ++changes;
304 _systemParams.MemsMaxSensorData = _memsMainBlock.Data_CountMax;
305 }
306 if (_systemParams.MemsCurrentCountSensorData != _memsMainBlock.Data_CountCurrent)
307 {
308 ++changes;
309 _systemParams.MemsCurrentCountSensorData = _memsMainBlock.Data_CountCurrent;
310 }
311 if (_systemParams.HWBatteryLevelStatus != batLevel)
312 {
313 ++changes;
314 _systemParams.HWBatteryLevelStatus = batLevel;
315 }
316 if (_systemParams.HWBatteryMV != batMV)
317 {
318 ++changes;
319 _systemParams.HWBatteryMV = batMV;
320 }
321
322 if (_systemParams.IntBatTimeSendUNIX != _memsMainBlock.Bat_SendTimeSendUNIX)
323 {
324 ++changes;
325 _systemParams.IntBatTimeSendUNIX = _memsMainBlock.Bat_SendTimeSendUNIX;
326 }
327
328 return changes;
329}
330
332{
333 _memsMainBlock.Bat_SendTimeSendUNIX = _systemParams.IntBatTimeSendUNIX;
334}
335
336
337///////////////////////////////////////////////////////////////////////////////////////
338// NFC
339///////////////////////////////////////////////////////////////////////////////////////
340
341
342void nfc_st25r3_OnMailboxData(uint8_t *data, uint16_t len)
343{
344// int stop=0;
345// writeLog("mam data");
346// this doesn't work, MailBox just doesn't work, giving up on it.....
347}
348
349/*
350 static void nfc_writeBattery(uint16_t addr)
351 {
352 uint8_t batCurrent = GetBatteryLevel(), batIn = 0;
353
354 HAL_StatusTypeDef status = nfc4_ReadEEPROM(_hi2c, addr, &batIn, sizeof(batIn));
355
356 if (status == HAL_OK)
357 {
358 if (batIn != batCurrent)
359 nfc4_WriteEEPROM(_hi2c, addr, &batCurrent, sizeof(batCurrent));
360 }
361 }
362 */
363
364/**
365 * @brief Read a value from an RTC backup register
366 *
367 * This function reads a 32-bit value from one of the RTC backup registers.
368 * These registers are retained during system standby mode and after system reset
369 * (as long as VDD is maintained or VBAT is supplied).
370 *
371 * @param backupRegister Backup register index (0-19 for STM32WL).
372 * Should use RTC_BKP_DRx constants defined in stm32wlxx_hal_rtc_ex.h
373 * (e.g., RTC_BKP_DR0=0, RTC_BKP_DR1=1, ..., RTC_BKP_DR19=19)
374 * @return uint32_t The 32-bit value stored in the backup register
375 */
376uint32_t getBackUpRegister(uint32_t backupRegister)
377{
378 return HAL_RTCEx_BKUPRead(&hrtc, backupRegister);
379}
380
381/**
382 * @brief Write a value to an RTC backup register
383 *
384 * This function writes a 32-bit value to one of the RTC backup registers.
385 * These registers are retained during system standby mode and after system reset
386 * (as long as VDD is maintained or VBAT is supplied).
387 *
388 * Use this function to save critical data before entering standby mode.
389 * On restart, read the values using getBackUpRegister() to check system state
390 * and restore necessary information.
391 *
392 * do not call HAL_PWR_EnableBkUpAccess and HAL_PWR_DisableBkUpAccess, the HAL_PWR_EnableBkUpAccess is calling in SystemClock_Config
393 *
394 * @param backupRegister Backup register index (0-19 for STM32WL).
395 * Should use RTC_BKP_DRx constants defined in stm32wlxx_hal_rtc_ex.h
396 * (e.g., RTC_BKP_DR0=0, RTC_BKP_DR1=1, ..., RTC_BKP_DR19=19)
397 * @param value The 32-bit value to store in the backup register
398 */
399void setBackUpRegister(uint32_t backupRegister, uint32_t value)
400{
401 //HAL_PWR_EnableBkUpAccess();
402 HAL_RTCEx_BKUPWrite(&hrtc, backupRegister, value);
403 //HAL_PWR_DisableBkUpAccess();
404}
405
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:152
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:243
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)
This function is executed in case of error occurrence.
Definition main.c:589
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:105
#define SPI1_CS_Pin
Definition main.h:149
#define SPI1_CS_GPIO_Port
Definition main.h:150
#define CLAMP(val, minVal, maxVal)
Clamp val to the closed interval [minVal, maxVal]. All three arguments are evaluated exactly once via...
Definition mydefs.h:50
#define INX_GET(nInx, nMax)
The circular index GET - for circular queue both direction Example usage:
Definition mydefs.h:65
void mems_RemoveLastData(uint8_t fromEndTo)
remove last data
Definition mymems.c:269
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:221
static flash_at25CS_t _flash
Definition mymems.c:31
uint8_t mems_WriteToSystemParams()
write data from memory to systemParams
Definition mymems.c:295
void mems_ReadFromSystemParams()
read data from NFC to mems block
Definition mymems.c:331
#define MEMS_DATA_BITS_BOUNDARY
Definition mymems.c:26
void mems_Init()
Initialise NFC and external flash; load the main block and system parameters. Verifies the flash sign...
Definition mymems.c:66
static void mens_MainBlockInit()
Definition mymems.c:47
static uint8_t mems_CheckCRC()
Definition mymems.c:41
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:195
mems_DataBlock_t * mems_InicBuffer(mems_DataType_t type)
Initialize the work buffer - _memsDataBlock.
Definition mymems.c:187
HAL_StatusTypeDef mems_Reset()
memory reset - remove sign from chip
Definition mymems.c:152
void setBackUpRegister(uint32_t backupRegister, uint32_t value)
Write a value to an RTC backup register.
Definition mymems.c:399
#define MEMS_MAINBLOCK_ADDR
Definition mymems.c:25
static mems_DataBlock_t _memsDataBlock
Definition mymems.c:34
#define MEMS_SIGN
Definition mymems.c:23
static void mems_SetCRC()
Definition mymems.c:36
HAL_StatusTypeDef mems_WriteMainBlock()
writing the main block on flash. The main block is stored on address 0
Definition mymems.c:142
#define MEMS_SIGN_BLOCK
Definition mymems.c:24
void nfc_st25r3_OnMailboxData(uint8_t *data, uint16_t len)
Definition mymems.c:342
static uint32_t mems_SetOffset(uint32_t offset, int16_t count)
move the offset in circular queue
Definition mymems.c:164
static uint32_t mems_GetAddr(uint32_t offset)
Definition mymems.c:181
uint32_t getBackUpRegister(uint32_t backupRegister)
Read a value from an RTC backup register.
Definition mymems.c:376
HAL_StatusTypeDef mems_Check(int8_t correct)
Check the memory consist.
Definition mymems.c:240
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:119
#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:29
mems_DataType_t
Type tag stored in each mems_DataBlock_t to identify the payload format. Used when reading back block...
Definition mymems.h:69
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:82
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
uint8_t calculateCrc(uint8_t *data, uint8_t len)
Calculate a CRC-8 checksum (Sensirion polynomial) over a byte buffer. Used to validate sensor I2C res...
Definition utils.c:13