kopia lustrzana https://github.com/SP8EBC/ParaTNC
353 wiersze
7.6 KiB
C
353 wiersze
7.6 KiB
C
/*
|
|
* nvm.c
|
|
*
|
|
* Created on: Nov 1, 2022
|
|
* Author: mateusz
|
|
*/
|
|
|
|
#include "nvm.h"
|
|
|
|
#define KB *1024
|
|
|
|
#ifdef STM32L471xx
|
|
#include <stm32l4xx_hal_cortex.h>
|
|
#include <stm32l4xx.h>
|
|
#include "./drivers/l4/flash_stm32l4x.h"
|
|
|
|
//!< Size of single flash memory page
|
|
#define NVM_PAGE_SIZE 2048
|
|
|
|
//!< How flash program operation are aligned, how many bytes must be programmed at once
|
|
#define NVM_WRITE_BYTE_ALIGN 8
|
|
|
|
#endif
|
|
|
|
//#define NVM_MEASUREMENT_OFFSET 0
|
|
|
|
//!< Size of NVM data logger in pages
|
|
#define NVM_MEASUREMENT_PAGES_USED 96
|
|
|
|
//!< Size of NVM data logger in bytes
|
|
#define NVM_MEASUREMENT_MAXIMUM_SIZ (NVM_PAGE_SIZE * NVM_MEASUREMENT_PAGES_USED)
|
|
|
|
//!< A macro to calculate start address of last page for NVM data logger
|
|
#define START_OF_LAST_NVM_PAGE (nvm_base_address + NVM_MEASUREMENT_MAXIMUM_SIZ - NVM_PAGE_SIZE)
|
|
|
|
//!< Base address of NVM data logger for device with 1MB of Flash
|
|
#define LOGGER_BASE_ADDRESS_1MB_DEVICE 0x08080000 // Page 256 from 511
|
|
|
|
#define LOGGER_BASE_ADDRESS_512K_DEVICE 0x08040000 // Page 256 from 383 (warning! there are no pages within 128-255)
|
|
uint32_t nvm_base_address = 0;
|
|
|
|
//!< Start address of flash page used currently for NVM
|
|
uint32_t nvm_current_page_address = 0;
|
|
|
|
/**
|
|
* Pointer to
|
|
*/
|
|
uint8_t * nvm_data_ptr = 0;
|
|
|
|
nvm_state_result_t nvm_general_state = NVM_UNINITIALIZED;
|
|
|
|
#define WAIT_FOR_PGM_COMPLETION \
|
|
while (1) {\
|
|
flash_status = FLASH_GetBank1Status(); \
|
|
\
|
|
if (flash_status == FLASH_BUSY) { \
|
|
; \
|
|
} \
|
|
else if (flash_status == FLASH_ERROR_PG) { \
|
|
nvm_general_state = NVM_PGM_ERROR; \
|
|
break; \
|
|
} \
|
|
else { \
|
|
break; \
|
|
} \
|
|
} \
|
|
|
|
void nvm_measurement_init(void) {
|
|
|
|
uint8_t data = 0;
|
|
|
|
// flash operation result
|
|
FLASH_Status flash_status = 0;
|
|
|
|
#if defined(STM32L471xx)
|
|
// check current flash size
|
|
if (FLASH_SIZE == 1024 KB) {
|
|
// 1024KB
|
|
nvm_base_address = LOGGER_BASE_ADDRESS_1MB_DEVICE;
|
|
}
|
|
else if (FLASH_SIZE == 512 KB) {
|
|
// 512KB
|
|
nvm_base_address = LOGGER_BASE_ADDRESS_512K_DEVICE;
|
|
}
|
|
else {
|
|
// unknown device ??
|
|
nvm_general_state = NVM_INIT_ERROR;
|
|
|
|
return;
|
|
}
|
|
|
|
// find the first non-erased page
|
|
for (uint32_t i = nvm_base_address; i < (nvm_base_address + NVM_MEASUREMENT_MAXIMUM_SIZ); i += NVM_PAGE_SIZE) {
|
|
// get the content of first byte
|
|
data = *((uint8_t*) i);
|
|
|
|
// check if data is in erased state
|
|
if (data == 0xFF) {
|
|
// first byte is erased, set data pointer to start of this page
|
|
nvm_data_ptr = (uint8_t*) i;
|
|
|
|
// and break from the loop
|
|
break;
|
|
}
|
|
|
|
// get the last byte of flash memory page
|
|
data = *(((uint8_t*) i + NVM_PAGE_SIZE - 1));
|
|
|
|
if (data == 0xFF) {
|
|
// last byte is not erased
|
|
nvm_data_ptr = (uint8_t*) i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if free flash memory page has been found
|
|
if (nvm_data_ptr != 0) {
|
|
// go through memory page and find clean (erased state) 64 bit word
|
|
for (int i = 0; i < NVM_PAGE_SIZE; i += NVM_WRITE_BYTE_ALIGN) {
|
|
// get this byte
|
|
data = *(nvm_data_ptr + i);
|
|
|
|
if (data == 0xFF) {
|
|
// rewind data pointer to this byte
|
|
nvm_data_ptr += i;
|
|
|
|
// and break the loop
|
|
break;
|
|
}
|
|
}
|
|
|
|
// program initialization mark
|
|
// unlock flash memory
|
|
FLASH_Unlock();
|
|
|
|
// enable programming
|
|
FLASH->CR |= FLASH_CR_PG;
|
|
|
|
*((uint32_t*)(nvm_data_ptr)) = 0xDEADBEEFu;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
|
|
*((uint32_t*)(nvm_data_ptr)+ 1) = 0x00000000u;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
|
|
if (nvm_general_state != NVM_PGM_ERROR) {
|
|
nvm_data_ptr += NVM_WRITE_BYTE_ALIGN;
|
|
|
|
nvm_general_state = NVM_OK;
|
|
}
|
|
|
|
// disable programming
|
|
FLASH->CR &= (0xFFFFFFFF ^ FLASH_CR_PG);
|
|
|
|
FLASH_Lock();
|
|
}
|
|
else {
|
|
// ig no there is no space on the flash memory
|
|
nvm_general_state = NVM_NO_SPACE_LEFT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
nvm_state_result_t nvm_measurement_store(nvm_measurement_t * data) {
|
|
|
|
nvm_state_result_t out = NVM_OK;
|
|
|
|
#if defined(STM32L471xx)
|
|
|
|
volatile uint32_t * src = (uint32_t *)data;
|
|
|
|
uint32_t next_page_addr = 0;
|
|
|
|
// flash operation result
|
|
FLASH_Status flash_status = 0;
|
|
|
|
// check if there is a room for storage
|
|
if (nvm_general_state == NVM_NO_SPACE_LEFT) {
|
|
// erase first page of NVM flash area
|
|
|
|
nvm_data_ptr = (uint8_t*)nvm_base_address;
|
|
|
|
flash_status = FLASH_ErasePage(nvm_data_ptr);
|
|
|
|
if (flash_status == FLASH_COMPLETE) {
|
|
nvm_general_state = NVM_OK;
|
|
}
|
|
else {
|
|
nvm_general_state = NVM_PGM_ERROR;
|
|
}
|
|
|
|
}
|
|
else {
|
|
// check if currently last page is used
|
|
if ((uint32_t)nvm_data_ptr < START_OF_LAST_NVM_PAGE) {
|
|
// if not check if next page of flash memory is erased or not
|
|
if (*(nvm_data_ptr + NVM_PAGE_SIZE) != 0xFF) {
|
|
// an address somewhere within the next page of memory
|
|
next_page_addr = (uint32_t)nvm_data_ptr + NVM_PAGE_SIZE;
|
|
|
|
// a start of next flash page
|
|
next_page_addr = (next_page_addr / NVM_PAGE_SIZE) * NVM_PAGE_SIZE;
|
|
|
|
flash_status = FLASH_ErasePage(next_page_addr);
|
|
|
|
if (flash_status != FLASH_COMPLETE) {
|
|
nvm_general_state = NVM_PGM_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FLASH_Unlock();
|
|
|
|
// check if NVM has been initialized and it is ready to work
|
|
if (nvm_general_state != NVM_UNINITIALIZED) {
|
|
// check if there is a room to store this measurement
|
|
if (nvm_general_state != NVM_NO_SPACE_LEFT) {
|
|
|
|
// enable programming
|
|
FLASH->CR |= FLASH_CR_PG;
|
|
|
|
// progam this measurement
|
|
for (int i = 0 ; i < NVM_RECORD_SIZE / 4; i++) {
|
|
*((uint32_t*)(nvm_data_ptr) + i) = *(src + i);
|
|
WAIT_FOR_PGM_COMPLETION
|
|
|
|
if (flash_status != FLASH_COMPLETE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// move data pointer
|
|
nvm_data_ptr += NVM_WRITE_BYTE_ALIGN;
|
|
|
|
// and check if an end has
|
|
if ((uint32_t)nvm_data_ptr < nvm_base_address + NVM_MEASUREMENT_MAXIMUM_SIZ) {
|
|
;
|
|
}
|
|
else {
|
|
out = NVM_NO_SPACE_LEFT;
|
|
nvm_general_state = NVM_NO_SPACE_LEFT;
|
|
}
|
|
|
|
// disable programming
|
|
FLASH->CR &= (0xFFFFFFFF ^ FLASH_CR_PG);
|
|
|
|
}
|
|
}
|
|
|
|
FLASH_Lock();
|
|
|
|
#endif
|
|
return out;
|
|
}
|
|
|
|
void nvm_erase_all(void) {
|
|
#if defined(STM32L471xx)
|
|
|
|
uint32_t base_address = 0;
|
|
|
|
FLASH_Unlock();
|
|
|
|
// check current flash size
|
|
if (FLASH_SIZE == 1024 KB) {
|
|
// 1024KB
|
|
base_address = 0x08080000;
|
|
}
|
|
else if (FLASH_SIZE == 512 KB) {
|
|
// 512KB
|
|
base_address = 0x08040000;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < NVM_MEASUREMENT_PAGES_USED; i++) {
|
|
FLASH_ErasePage(base_address + (i * NVM_PAGE_SIZE));
|
|
}
|
|
|
|
FLASH_Lock();
|
|
#endif
|
|
}
|
|
|
|
void nvm_test_prefill(void) {
|
|
#if defined(STM32L471xx)
|
|
|
|
uint32_t * base_address = 0;
|
|
|
|
// flash operation result
|
|
FLASH_Status flash_status = 0;
|
|
|
|
FLASH_Unlock();
|
|
|
|
// enable programming
|
|
FLASH->CR |= FLASH_CR_PG;
|
|
|
|
// check current flash size
|
|
if (FLASH_SIZE == 1024 KB) {
|
|
// 1024KB
|
|
base_address = (uint32_t *)0x08080000;
|
|
}
|
|
else if (FLASH_SIZE == 512 KB) {
|
|
// 512KB
|
|
base_address = (uint32_t *)0x08040000;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
|
|
// program first 10 pages of flash with 0xABCDABCD / 0x99889988
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
// flash programming must be 64 bit (8 bytes) aligned
|
|
for (int j = 0; j < NVM_PAGE_SIZE / 8; j++) {
|
|
*(base_address++) = 0xABCDABCD;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
|
|
*(base_address++) = 0x99889988;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
}
|
|
}
|
|
|
|
if (FLASH_SIZE == 1024 KB) {
|
|
// 1024KB
|
|
base_address = (uint32_t *)(0x08080000 + 11 * NVM_PAGE_SIZE);
|
|
}
|
|
else if (FLASH_SIZE == 512 KB) {
|
|
// 512KB
|
|
base_address = (uint32_t *)(0x08040000 + 11 * NVM_PAGE_SIZE);
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
|
|
for (int i = 11; i < NVM_MEASUREMENT_PAGES_USED; i++) {
|
|
// flash programming must be 64 bit (8 bytes) aligned
|
|
for (int j = 0; j < NVM_PAGE_SIZE / 8; j++) {
|
|
*(base_address++) = 0x12345678;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
|
|
*(base_address++) = 0x99999999;
|
|
WAIT_FOR_PGM_COMPLETION
|
|
}
|
|
}
|
|
// disable programming
|
|
FLASH->CR &= (0xFFFFFFFF ^ FLASH_CR_PG);
|
|
|
|
FLASH_Lock();
|
|
|
|
#endif
|
|
}
|