try to fix submodule
This commit is contained in:
49
firmware/lib/Arduino-FOC-drivers/src/settings/samd/README.md
Normal file
49
firmware/lib/Arduino-FOC-drivers/src/settings/samd/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# SAMD21 settings driver
|
||||
|
||||
Driver for storing settings on SAMD21 chips.
|
||||
|
||||
There are two options:
|
||||
|
||||
1. **RWW Flash** \
|
||||
Some SAMD21 chips have a seperate RWW flash area, of 2kB-8kB size. This area is seperate from the main flash array. \
|
||||
Note: this method is implemented and tested.
|
||||
|
||||
2. **EEPROM emulation** \
|
||||
All SAMD21s support EEPROM emulation, where an area of the main flash is reserved for the application storage. \
|
||||
:warning: This method is not yet implemented fully, and untested.
|
||||
|
||||
## Using RWW flash
|
||||
|
||||
To use the RWW flash to store settings, you have to make sure the flash region is not locked (you can set the lock fuses using MCP Studio or other SAM development tools).
|
||||
|
||||
Otherwise there is nothing special to do. When reprogramming the chip, be careful not to erase the RWW area.
|
||||
|
||||
You can use multiple settings objects to store to different areas of the RWW.
|
||||
To do so, specify an offset to the constructor:
|
||||
|
||||
```c++
|
||||
SAMDNVMSettingsStorage settings0 = SAMDNVMSettingsStorage();
|
||||
SAMDNVMSettingsStorage settings1 = SAMDNVMSettingsStorage(NVMCTRL_ROW_SIZE);
|
||||
SAMDNVMSettingsStorage settings2 = SAMDNVMSettingsStorage(NVMCTRL_ROW_SIZE*2);
|
||||
```
|
||||
|
||||
Note: the offset must be a multiple of the flash memory row size, typically 256 bytes.
|
||||
|
||||
|
||||
## Using EEPROM emulation
|
||||
|
||||
TODO implement and test this method
|
||||
|
||||
To use the EEPROM emulation, use a tool like MCP Studio to set the chip fuses to reserve an area of flash for EEPROM emulation:
|
||||
|
||||

|
||||
|
||||
Normally 256 bytes (one flash page) should be plenty for SimpleFOC settings... Obviously, the area you reserve for EEPROM can't be used for your main program.
|
||||
|
||||
Add a build-flag to your build to set the base address of your EEPROM memory:
|
||||
|
||||
`-DSIMPLEFOC_SAMDNVMSETTINGS_BASE=0x003FF800`
|
||||
|
||||
Then use the settings as normal.
|
||||
|
||||
You'll have to adjust your board files to exclude the EEPROM area in the ldscript to prevent it being erased when you re-program, if you care to keep your settings when reflashing.
|
||||
@@ -0,0 +1,164 @@
|
||||
|
||||
|
||||
|
||||
#include "./SAMDNVMSettingsStorage.h"
|
||||
|
||||
|
||||
#if defined(_SAMD21_)
|
||||
|
||||
#include "communication/SimpleFOCDebug.h"
|
||||
|
||||
|
||||
SAMDNVMSettingsStorage::SAMDNVMSettingsStorage(uint32_t offset) {
|
||||
_offset = offset;
|
||||
};
|
||||
|
||||
SAMDNVMSettingsStorage::~SAMDNVMSettingsStorage(){};
|
||||
|
||||
void SAMDNVMSettingsStorage::init(){
|
||||
SettingsStorage::init();
|
||||
reset();
|
||||
};
|
||||
|
||||
|
||||
|
||||
void SAMDNVMSettingsStorage::reset(){
|
||||
_currptr = (uint8_t*) SIMPLEFOC_SAMDNVMSETTINGS_BASE + _offset; // add offset to NVM base address
|
||||
};
|
||||
|
||||
|
||||
|
||||
void SAMDNVMSettingsStorage::beforeLoad(){
|
||||
reset();
|
||||
};
|
||||
|
||||
|
||||
void SAMDNVMSettingsStorage::beforeSave(){
|
||||
reset();
|
||||
_writeIndex = 0;
|
||||
|
||||
// set manual write mode
|
||||
_ctlB = NVMCTRL->CTRLB.reg;
|
||||
NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_MANW;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) {};
|
||||
// unlock region - user can do it with fuses
|
||||
// erase rows
|
||||
// TODO handle case that it is more than one row
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)_currptr - RWWEE_BASE) / 2;
|
||||
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK;
|
||||
NVMCTRL->INTFLAG.bit.ERROR = 0;
|
||||
NVMCTRL->CTRLA.reg = 0x1A | NVMCTRL_CTRLA_CMDEX_KEY;
|
||||
delay(1);
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) {};
|
||||
if (NVMCTRL->INTFLAG.bit.ERROR == 1)
|
||||
SimpleFOCDebug::println("NVM erase error ", NVMCTRL->STATUS.reg);
|
||||
else
|
||||
SimpleFOCDebug::println("NVM erased row @", (int)_currptr);
|
||||
};
|
||||
|
||||
|
||||
void SAMDNVMSettingsStorage::afterSave() {
|
||||
if (_writeIndex>0)
|
||||
flushPage();
|
||||
// restore ctlb
|
||||
delay(1);
|
||||
NVMCTRL->CTRLB.reg =_ctlB;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) {};
|
||||
}
|
||||
|
||||
|
||||
void SAMDNVMSettingsStorage::flushPage(){
|
||||
// if we have an odd number of bytes, pad with 0xFF
|
||||
if (_writeIndex%2==1) {
|
||||
_writeBuffer[_writeIndex++] = 0xFF;
|
||||
}
|
||||
// erase page buffer
|
||||
// NVMCTRL->ADDR.reg = ((uint32_t)_currptr - RWWEE_BASE) / 2;
|
||||
// NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY;
|
||||
// while (NVMCTRL->INTFLAG.bit.READY == 0) {};
|
||||
// copy writeBuffer to NVM, using 16-bit writes
|
||||
uint16_t* src = (uint16_t*)_writeBuffer;
|
||||
uint16_t* dst = (uint16_t*)_currptr;
|
||||
for (int i=0;i<_writeIndex/2;i++) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
// write page
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)_currptr - RWWEE_BASE) / 2;
|
||||
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK;
|
||||
NVMCTRL->INTFLAG.bit.ERROR = 0;
|
||||
NVMCTRL->CTRLA.reg = 0x1C | NVMCTRL_CTRLA_CMDEX_KEY;
|
||||
delay(1);
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) {};
|
||||
if (NVMCTRL->INTFLAG.bit.ERROR == 1)
|
||||
SimpleFOCDebug::println("NVM write error ", NVMCTRL->STATUS.reg);
|
||||
else
|
||||
SimpleFOCDebug::println("NVM wrote page @", (int)_currptr);
|
||||
// reset writeBuffer pointer and advance currptr to next page
|
||||
_writeIndex = 0;
|
||||
_currptr+=NVMCTRL_PAGE_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int SAMDNVMSettingsStorage::readBytes(void* valueToSet, int numBytes) {
|
||||
uint8_t* bytes = (uint8_t*)valueToSet;
|
||||
for (int i=0;i<numBytes;i++) {
|
||||
uint8_t val = *_currptr++;
|
||||
bytes[i] = val;
|
||||
}
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
int SAMDNVMSettingsStorage::writeBytes(void* value, int numBytes) {
|
||||
uint8_t* bytes = (uint8_t*)value;
|
||||
for (int i=0;i<numBytes;i++) {
|
||||
_writeBuffer[_writeIndex] = *bytes++;
|
||||
_writeIndex++;
|
||||
if (_writeIndex==NVMCTRL_PAGE_SIZE)
|
||||
flushPage();
|
||||
}
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::readByte(uint8_t* valueToSet){
|
||||
uint8_t val;
|
||||
uint8_t num = readBytes(&val, 1);
|
||||
if (num==1)
|
||||
*valueToSet = val;
|
||||
return num;
|
||||
};
|
||||
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::readFloat(float* valueToSet){
|
||||
float val;
|
||||
uint8_t num = readBytes(&val, 4);
|
||||
if (num==4)
|
||||
*valueToSet = val;
|
||||
return num;
|
||||
};
|
||||
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::readInt(uint32_t* valueToSet){
|
||||
uint32_t val;
|
||||
uint8_t num = readBytes(&val, 4);
|
||||
if (num==4)
|
||||
*valueToSet = val;
|
||||
return num;
|
||||
};
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::writeByte(uint8_t value){
|
||||
return writeBytes(&value, 1);
|
||||
};
|
||||
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::writeFloat(float value){
|
||||
return writeBytes(&value, 4);
|
||||
};
|
||||
|
||||
|
||||
uint8_t SAMDNVMSettingsStorage::writeInt(uint32_t value){
|
||||
return writeBytes(&value, 4);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SAMD can write to their onboard NVM (flash). This class implements the SettingsStorage interface
|
||||
* for storing settings in NVM.
|
||||
*
|
||||
* There are two suggested strategies for using the NVM for storing settings:
|
||||
*
|
||||
* 1. On chips which have it, use the RWWEE (Read While Write EEPROM) section of the NVM. This is
|
||||
* a small section of the NVM which can be written to while the rest of the NVM is being read.
|
||||
* This is the default strategy used by this class. The size of the RWWEE section varies by chip,
|
||||
* but is at least 2kB. It is seperate from the main flash memory, so doesn't reduce the amount
|
||||
* of flash available for your program.
|
||||
*
|
||||
* 2. On chips which don't have a RWWEE section, you can configure a EEPROM section in the NVM. This
|
||||
* will be at the end of the main NVM, and therefore reduces the flash available for your program.
|
||||
*
|
||||
* In either case, you must make sure your board definition file has the correct NVM settings to prevent
|
||||
* the configuration from being overwritten by the Arduino IDE / your programmer.
|
||||
*
|
||||
* By default, this class will use the RWWEE section at address 0x00400000.
|
||||
* To change it, use the build flag SIMPLEFOC_SAMDNVMSETTINGS_BASE to set the base address of your choice.
|
||||
*
|
||||
* You can pass an offset to the constructor of this class. This allows you to store multiple sets of
|
||||
* settings in the NVM. The offset should be a multiple of the ROWSIZE (256 bytes).
|
||||
*
|
||||
* The memory rows (normally 1 row, but could be more if you save a *lot*) containing settings are always
|
||||
* erased before writing. Don't store other data within the same memory rows.
|
||||
*
|
||||
* Don't save to NVM unnecessarily. It has a limited number of write cycles, and writing takes time.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(_SAMD21_)
|
||||
|
||||
#include "../SettingsStorage.h"
|
||||
|
||||
#define RWWEE_BASE 0x00400000
|
||||
|
||||
#if !defined(SIMPLEFOC_SAMDNVMSETTINGS_BASE)
|
||||
#define SIMPLEFOC_SAMDNVMSETTINGS_BASE RWWEE_BASE
|
||||
#endif
|
||||
|
||||
|
||||
class SAMDNVMSettingsStorage : public SettingsStorage {
|
||||
public:
|
||||
SAMDNVMSettingsStorage(uint32_t offset = 0x0);
|
||||
~SAMDNVMSettingsStorage();
|
||||
|
||||
void init() override;
|
||||
|
||||
protected:
|
||||
uint8_t readByte(uint8_t* valueToSet) override;
|
||||
uint8_t readFloat(float* valueToSet) override;
|
||||
uint8_t readInt(uint32_t* valueToSet) override;
|
||||
|
||||
uint8_t writeByte(uint8_t value) override;
|
||||
uint8_t writeFloat(float value) override;
|
||||
uint8_t writeInt(uint32_t value) override;
|
||||
|
||||
void beforeSave() override;
|
||||
void afterSave() override;
|
||||
void beforeLoad() override;
|
||||
|
||||
|
||||
void reset();
|
||||
int readBytes(void* valueToSet, int numBytes);
|
||||
int writeBytes(void* value, int numBytes);
|
||||
void flushPage();
|
||||
|
||||
uint32_t _offset; // offset into NVRAM to store settings
|
||||
|
||||
uint32_t _ctlB;
|
||||
uint8_t* _currptr; // pointer to current location in NVM
|
||||
int _writeIndex; // index into current page being written
|
||||
uint8_t _writeBuffer[NVMCTRL_PAGE_SIZE]; // buffer for writing to NVM
|
||||
};
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
Reference in New Issue
Block a user