try to fix submodule

This commit is contained in:
2023-11-09 19:02:15 -05:00
parent c1d45aa443
commit deea94b076
366 changed files with 40228 additions and 2 deletions

View 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:
![](eeprom_emulation_screenshot.jpg)
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.

View File

@@ -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

View File

@@ -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