Skip to content

Commit

Permalink
Add $NVM command for supporting User Storage Space
Browse files Browse the repository at this point in the history
Use AT$NVM=0,123 to store value 123 in user space 0
+OK=1,123
Use AT$NVM=0 to read value previously stored
+OK=123

It currently supports 4 user spaces (0 to 3) and values are 8 bits unsigned
  • Loading branch information
disk91 committed Oct 27, 2022
1 parent 20d9c5e commit fb8b5b8
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 2 deletions.
22 changes: 22 additions & 0 deletions src/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2055,6 +2055,27 @@ static void get_session(void)
}



// Read and Store a User data into the NVM area
// AT$NVM=0 read data at address 0
// AT$NVM=0,223 write 223 at address 0
static void set_nvm(atci_param_t *param) {
uint32_t adr, value;
if (!atci_param_get_uint(param, &adr)) abort(ERR_PARAM);
if (adr >= USER_NVM_MAX_SIZE) abort(ERR_PARAM);
if (param->offset < param->length) {
if (!atci_param_is_comma(param)) abort(ERR_PARAM);
if (!atci_param_get_uint(param, &value)) abort(ERR_PARAM);
if (value >= 256) abort(ERR_PARAM);
user_nvm.values[adr] = value;
userNvm_process();
OK("%d,%d",(int)adr,(int)value);
} else {
OK("%d",user_nvm.values[adr]);
}
}


static const atci_command_t cmds[] = {
{"+UART", NULL, set_uart, get_uart, NULL, "Configure UART interface"},
{"+VER", NULL, NULL, get_version_comp, NULL, "Firmware version and build time"},
Expand Down Expand Up @@ -2125,6 +2146,7 @@ static const atci_command_t cmds[] = {
{"$SESSION", NULL, NULL, get_session, NULL, "Get network session information"},
{"$CW", cw, NULL, NULL, NULL, "Start continuous carrier wave transmission"},
{"$CM", cm, NULL, NULL, NULL, "Start continuous modulated FSK transmission"},
{"$NVM", NULL, set_nvm, NULL, NULL, "Store / Read data from Non Volatile Memory"},
ATCI_COMMAND_CLAC,
ATCI_COMMAND_HELP};

Expand Down
37 changes: 35 additions & 2 deletions src/nvm.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "nvm.h"
#include <assert.h>
#include <string.h>
#include <strings.h>
#include <stm/include/stm32l072xx.h>
#include <loramac-node/src/mac/LoRaMacTypes.h>
#include <loramac-node/src/mac/LoRaMac.h>
Expand All @@ -11,7 +12,7 @@
#include "part.h"
#include "utils.h"

#define NUMBER_OF_PARTS 8
#define NUMBER_OF_PARTS 9


/* The following partition sizes have been derived from the in-memory size of
Expand All @@ -30,6 +31,7 @@
#define REGION1_PART_SIZE 32
#define REGION2_PART_SIZE 1536
#define CLASSB_PART_SIZE 32
#define USER_NVM_PART_SIZE 12


// Make sure each data structure fits into its fixed-size partition
Expand All @@ -41,6 +43,7 @@ static_assert(sizeof(SecureElementNvmData_t) <= SE_PART_SIZE, "SecureElement NVM
static_assert(sizeof(RegionNvmDataGroup1_t) <= REGION1_PART_SIZE, "RegionGroup1 NVM data too long");
static_assert(sizeof(RegionNvmDataGroup2_t) <= REGION2_PART_SIZE, "RegionGroup2 NVM data too long");
static_assert(sizeof(LoRaMacClassBNvmData_t) <= CLASSB_PART_SIZE, "ClassB NVM data too long");
static_assert(sizeof(userNvm_t) <= USER_NVM_PART_SIZE, "User NVM data too long");


// And also make sure that NVM data fits into the EEPROM twice. This is
Expand All @@ -53,7 +56,8 @@ static_assert(
SE_PART_SIZE +
REGION1_PART_SIZE +
REGION2_PART_SIZE +
CLASSB_PART_SIZE
CLASSB_PART_SIZE +
USER_NVM_PART_SIZE
<= (DATA_EEPROM_BANK2_END - DATA_EEPROM_BASE + 1 - PART_TABLE_SIZE(NUMBER_OF_PARTS)) / 2,
"NVM data does not fit into a single EEPROM bank");

Expand All @@ -71,6 +75,8 @@ static part_block_t nvm = {

struct nvm_parts nvm_parts;

userNvm_t user_nvm = { 0 };

sysconf_t sysconf = {
.uart_baudrate = DEFAULT_UART_BAUDRATE,
.uart_timeout = 1000,
Expand Down Expand Up @@ -147,6 +153,11 @@ void nvm_init(void)
nvm_parts.classb.dsc->size != CLASSB_PART_SIZE)
goto retry;

if ((part_find(&nvm_parts.user, &nvm, "user") &&
part_create(&nvm_parts.user, &nvm, "user", USER_NVM_PART_SIZE)) ||
nvm_parts.user.dsc->size != USER_NVM_PART_SIZE)
goto retry;

size_t size;
const uint8_t *p = part_mmap(&size, &nvm_parts.sysconf);
if (check_block_crc(p, sizeof(sysconf))) {
Expand All @@ -155,6 +166,17 @@ void nvm_init(void)
} else {
log_debug("Invalid system configuration checksum, using defaults");
}

p = part_mmap(&size, &nvm_parts.user);
if (check_block_crc(p, sizeof(user_nvm))) {
log_debug("Restoring user data from NVM");
memcpy(&user_nvm, p, sizeof(user_nvm));
} else {
log_debug("Invalid user data checksum, using defaults");
user_nvm.magic = USER_NVM_MAGIC;
bzero(user_nvm.values,USER_NVM_MAX_SIZE);
}

return;

retry:
Expand Down Expand Up @@ -192,3 +214,14 @@ void sysconf_process(void)
sysconf_modified = false;
}


void userNvm_process(void)
{

if (update_block_crc(&user_nvm, sizeof(user_nvm))) {
log_debug("Saving user data to NVM");
if (!part_write(&nvm_parts.user, 0, &user_nvm, sizeof(user_nvm)))
log_error("Error while writing user data to NVM");
}

}
11 changes: 11 additions & 0 deletions src/nvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,29 @@ struct nvm_parts {
part_t region1;
part_t region2;
part_t classb;
part_t user;
};

#define USER_NVM_MAX_SIZE 4 // maximum allows values inside the User Nvm area
#define USER_NVM_MAGIC 0xD15C9101
typedef struct userNvm_s {
uint32_t magic;
uint8_t values[USER_NVM_MAX_SIZE];
uint32_t crc32;
} userNvm_t;


extern struct nvm_parts nvm_parts;
extern sysconf_t sysconf;
extern bool sysconf_modified;
extern uint16_t nvm_flags;
extern userNvm_t user_nvm;

void nvm_init(void);

int nvm_erase(void);

void sysconf_process(void);
void userNvm_process(void);

#endif // _NVM_H_

0 comments on commit fb8b5b8

Please sign in to comment.