Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Nvm CTX to restore session between power cycles #678

Closed
BenAtPip opened this issue Feb 13, 2019 · 6 comments
Closed

Using Nvm CTX to restore session between power cycles #678

BenAtPip opened this issue Feb 13, 2019 · 6 comments

Comments

@BenAtPip
Copy link

Hi all,

Does anyone have experience power cycling their LoRaMac-node device and restoring the context in order to retain a join? The hope is to use a LoRa module as a stand alone radio for a main microprocessor. In order to reduce sleep current I want to be able to completely cut power from the LoRa radio module

I can successfully restore context without power cycling my end device (i.e I can see a repeated frame with a restored NvmCtx structure) but following a soft reset the restoration fails, and no frame is seen by the back end. Is there another process which is required to be carried out for the device to resume it's session?

I am using firmware heavily based off of the STM cube LRWAN release (1.2.1). Any insight would be appreciated

@mluis1
Copy link
Contributor

mluis1 commented Feb 14, 2019

Hi @BenAtPip,

We don't know which modifications have been done in the stm32cube-lrwan by ST or by you ("using firmware heavily based ..."). This makes it very hard to help you. To have better support on this we would recommend that you contact the ST support.

That said, making an end-device operate as you described should be possible using the NvmCtxMgmt.c/h module.

Currently, we are validating that this module works as expected and so far it looks to be working well.
The only issue that we discovered up until now is that the EEPROM drivers for the NucleoL476 platform aren't working as expected. The FLASH memory write fails for an yet unknown reason.

@catsup
Copy link

catsup commented Feb 14, 2019

One question springs to mind - how long are the devices expected to last, seeing that FLASH ls usually limited to 10000 writes ?

With one uplink every 1 minutes for example, that would be one week (10 weeks if using EEPROM).

Is the NvmCtxMgmt module doing wear leveling or something the like ?

@mluis1
Copy link
Contributor

mluis1 commented Feb 14, 2019

NvmCtxMgmt is not doing wear leveling. As such you are right the MCU FLASH memory can become unusable.

Our recommendation would be to use an external NVM memory that supports a higher level of write cycles.

Another thing that could be done is to not save to the flash every time the MAC layer notifies to do so but, maybe every few up links or few minutes.
In such case the manufacturer should activate the MCU brown out detector in order to detect as soon as possible that the main power supply is dropping and perform a NVM store. The issue here is to know if the amount of energy is enough to perform the NVM store operation. To overcome this issue one could put a capacitor on the end-device board big enough to supply the MCU as well as the NVM while the power supply decreases.

@BenAtPip
Copy link
Author

I am using an external memory source - an active microcontroller in my application. So NVM wear is not an issue in this instance.

As for the modifications - this is simply loading and unloading of NVM context via UART using modified AT commands to obtain and restore the context. I use the following function to load context from the loaded memory

LoRaMacStatus_t lora_join_configuration_set(LoRaMacCtxs_t* radioContext)
{
	LoRaMacStatus_t status = LORAMAC_STATUS_ERROR;
	MibRequestConfirm_t mib;
	mib.Type = MIB_NVM_CTXS;
	mib.Param.Contexts = (LoRaMacCtxs_t*) radioContext;
	status = LoRaMacMibSetRequestConfirm(&mib);

	return status;
}

I also invoke LoRaMacStart(); following this to ensure the radio is not in stop mode. Looking at the ST project it appears not to be upto date with the NvmCtxMgmt module, but I can use that as a jumping point

@BenAtPip
Copy link
Author

BenAtPip commented Feb 20, 2019

Found the root issue here:

The issue I was experiencing was due to the fact that the network I was connecting to was operating on Ver 1.1.

The network join procedure indicates to the device which version of the standard to use. In LoRaMaxCrypto module this information is not stored in the LoRaMaxCryptoNvmCtx_t type, but rather in the LoRaMaxCryptoCtx_t.

As a result the MIC for frames sent by the device when the context was restored were incorrect, as they were being transmitted with the 1.0 MIC calculation method on the 1.1 network.

I propose the fix for this is to simply move the LrWanVersion field into the LoRaMaxCryptoNvmCtx_t type and change all references to this to reflect the change. I've been able to retain join sessions as a result of this change:

Changed type definition
`

/*

  • LoRaMac Crypto Non Volatile Context structure
    /
    typedef struct sLoRaMacCryptoNvmCtx
    {
    /
    • Device nonce is a counter starting at 0 when the device is initially
    • powered up and incremented with every JoinRequest.
      /
      uint16_t DevNonce;
      /
    • JoinNonce is a device specific counter value (that never repeats itself)
    • provided by the join server and incremented with every JoinAccept message.
      /
      uint32_t JoinNonce;
      /
    • Uplink frame counter.
      /
      uint32_t FCntUp;
      /
    • Network downlink frame counter.
      /
      uint32_t NFCntDown;
      /
    • Application downlink frame counter.
      /
      uint32_t AFCntDown;
      /
    • Downlink frame counter for LoRaWAN 1.0 Server
      /
      uint32_t FCntDown;
      /
      !
    • Multicast downlink counter for index 0
      /
      uint32_t McFCntDown0;
      /
      !
    • Multicast downlink counter for index 1
      /
      uint32_t McFCntDown1;
      /
      !
    • Multicast downlink counter for index 2
      /
      uint32_t McFCntDown2;
      /
      !
    • Multicast downlink counter for index 3
      /
      uint32_t McFCntDown3;
      /
    • RJcount1 is a counter incremented with every Rejoin request Type 1 frame transmitted.
      /
      uint16_t RJcount1;
      /
    • LastDownFCnt stores the information which frame counter was used to unsecure the last frame.
    • This information is needed to compute ConfFCnt in B1 block for the MIC.
      /
      uint32_t
      LastDownFCnt;
      /*
    • Stores the information if the device is connected to a LoRaWAN network
    • server with prior to 1.1.0 implementation.
      */
      Version_t LrWanVersion;
      }LoRaMacCryptoNvmCtx_t;

/*

  • LoRaMac Crypto Context structure
    */
    typedef struct sLoRaMacCryptoCtx
    {

    /*

    • RJcount0 is a counter incremented with every Type 0 or 2 Rejoin frame transmitted.
      /
      uint16_t RJcount0;
      /
    • Non volatile module context structure
      /
      LoRaMacCryptoNvmCtx_t
      NvmCtx;
      /*
    • Callback function to notify the upper layer about context change
      */
      EventNvmCtxChanged EventCryptoNvmCtxChanged;

    /*

    • Added elements for derived keys
      */
      }LoRaMacCryptoCtx_t;

`

And refactor all references to version within the module from

CryptoCtx.LrWanVersion
to
CryptoCtx.NvmCtx->LrWanVersion

@djaeckle
Copy link

djaeckle commented Mar 4, 2019

Hi BenAtPip,

thanks for the change request. I think your proposition is valid. We will provide a fix here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants