Commit 6e4853a6 authored by Jake Read's avatar Jake Read
Browse files

try from scratch

parent 76447143
......@@ -12,4 +12,3 @@
platform = atmelsam
board = adafruit_feather_m4
framework = arduino
lib_deps = cmaglie/FlashStorage@^1.0.0
......@@ -13,6 +13,7 @@ is; no warranty is provided, and users accept all liability.
*/
#include "step_cl.h"
#include "../utils/FlashStorage.h"
Step_CL* Step_CL::instance = 0;
......@@ -46,27 +47,72 @@ void Step_CL::init(void){
//lut = flash_lut.read();
}
FlashStorage(flash_store, float);
#define BYTES_PER_PAGE 512
#define FLOATS_PER_PAGE 128
#define PAGES_PER_BLOCK 16 // for 8192 bytes / block
#define LUT_SIZE 128
//const float __attribute__((__aligned__(BYTES_PER_PAGE))) lut[LUT_SIZE] = {};
//const void* page_ptr;
//static float buffer[FLOATS_PER_PAGE];
//static uint32_t bi;
//FlashClass flashClass((const uint8_t*)lut, BYTES_PER_PAGE); // try w/ constructor values ?
typedef struct {
float f[LUT_SIZE];
} flts;
flts inbuf;
uint32_t bi = 0;
FlashStorage(flash_storage, flts);
void flash_write_init(void){
}
void flash_write_page(void){
sysError("writing");
flash_storage.write(inbuf);
sysError("written");
// sysError("unlocking block");
// NVMCTRL->ADDR.reg = (uint32_t)((const uint8_t*)(lut));
// NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_UR;
// while(NVMCTRL->STATUS.bit.READY == 0);
// sysError("erasing block");
// //flashClass.erase((const uint8_t*)lut, 0);
// NVMCTRL->ADDR.reg = (uint32_t)((const uint8_t*)(lut));
// NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
// // is it hung, or is there an error to catch ?
// // hung !
// //while(NVMCTRL->STATUS.bit.READY == 0);
// sysError("writing page");
// flashClass.write((const uint8_t*)lut, (const uint8_t*)buffer, BYTES_PER_PAGE);
}
void flash_write_value(float val){
flash_store.write(val);
inbuf.f[bi ++] = val;
if(bi >= LUT_SIZE){
flash_write_page();
}
}
void Step_CL::print_table(void){
for(uint16_t e = 0; e < 4; e ++){
float ra = flash_store.read();
sysError("e: " + String(e) + " ra: " + String(ra, 4));
sysError("reading");
flts read = flash_storage.read();
for(uint16_t e = 0; e < LUT_SIZE; e ++){
sysError(String(read.f[e]));
delay(5);
}
}
// the calib routine
boolean Step_CL::calibrate(void){
flash_write_value(100.0F);
flash_write_init();
for(uint8_t i = 0; i < LUT_SIZE; i ++){
flash_write_value(i * 1.1F);
}
return true;
// (1) first, build a table for 200 full steps w/ encoder averaged values at each step
float phase_angle = 0.0F;
......@@ -215,7 +261,7 @@ boolean Step_CL::calibrate(void){
delay(10);
}
// ok, have the real angle (ra) at the encoder tick (e), now write it
flash_write_value(ra); // this just happens in order, we zeroe'd out global counters at the start
//flash_write_value(ra); // this just happens in order, we zeroe'd out global counters at the start
} // end sweep thru 2^14 pts
sysError("calib complete");
return true; // went OK
......
......@@ -20,8 +20,6 @@ is; no warranty is provided, and users accept all liability.
#include "step_a4950.h"
#include "enc_as5047.h"
#include "FlashStorage.h"
class Step_CL {
private:
static Step_CL* instance;
......@@ -38,6 +36,8 @@ class Step_CL {
//step_cl_calib_table_t lut; // not even this works ?? too big ??
};
extern const float lut[];
extern Step_CL* step_cl;
#endif
\ No newline at end of file
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
Written by Cristian Maglie
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "FlashStorage.h"
static const uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
FlashClass::FlashClass(const void *flash_addr, uint32_t size) :
PAGE_SIZE(pageSizes[NVMCTRL->PARAM.bit.PSZ]),
PAGES(NVMCTRL->PARAM.bit.NVMP),
MAX_FLASH(PAGE_SIZE * PAGES),
#if defined(__SAMD51__)
ROW_SIZE(MAX_FLASH / 64),
#else
ROW_SIZE(PAGE_SIZE * 4),
#endif
flash_address((volatile void *)flash_addr),
flash_size(size)
{
}
static inline uint32_t read_unaligned_uint32(const void *data)
{
union {
uint32_t u32;
uint8_t u8[4];
} res;
const uint8_t *d = (const uint8_t *)data;
res.u8[0] = d[0];
res.u8[1] = d[1];
res.u8[2] = d[2];
res.u8[3] = d[3];
return res.u32;
}
#if defined(__SAMD51__)
// Invalidate all CMCC cache entries if CMCC cache is enabled.
static void invalidate_CMCC_cache()
{
if (CMCC->SR.bit.CSTS) { // CR -> SR
CMCC->CTRL.bit.CEN = 0;
while (CMCC->SR.bit.CSTS) {}
CMCC->MAINT0.bit.INVALL = 1;
CMCC->CTRL.bit.CEN = 1;
}
}
#endif
void FlashClass::write(const volatile void *flash_ptr, const void *data, uint32_t size)
{
// Calculate data boundaries
size = (size + 3) / 4;
volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr;
const uint8_t *src_addr = (uint8_t *)data;
// Disable automatic page write
#if defined(__SAMD51__)
NVMCTRL->CTRLA.bit.WMODE = 0;
while (NVMCTRL->STATUS.bit.READY == 0) { }
// Disable NVMCTRL cache while writing, per SAMD51 errata.
bool original_CACHEDIS0 = NVMCTRL->CTRLA.bit.CACHEDIS0;
bool original_CACHEDIS1 = NVMCTRL->CTRLA.bit.CACHEDIS1;
NVMCTRL->CTRLA.bit.CACHEDIS0 = true;
NVMCTRL->CTRLA.bit.CACHEDIS1 = true;
#else
NVMCTRL->CTRLB.bit.MANW = 1;
#endif
// Do writes in pages
while (size) {
// Execute "PBC" Page Buffer Clear
#if defined(__SAMD51__)
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_PBC;
while (NVMCTRL->INTFLAG.bit.DONE == 0) { }
#else
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
#endif
// Fill page buffer
uint32_t i;
for (i=0; i<(PAGE_SIZE/4) && size; i++) {
*dst_addr = read_unaligned_uint32(src_addr);
src_addr += 4;
dst_addr++;
size--;
}
// Execute "WP" Write Page
#if defined(__SAMD51__)
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_WP;
while (NVMCTRL->INTFLAG.bit.DONE == 0) { }
invalidate_CMCC_cache();
// Restore original NVMCTRL cache settings.
NVMCTRL->CTRLA.bit.CACHEDIS0 = original_CACHEDIS0;
NVMCTRL->CTRLA.bit.CACHEDIS1 = original_CACHEDIS1;
#else
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
#endif
}
}
void FlashClass::erase(const volatile void *flash_ptr, uint32_t size)
{
const uint8_t *ptr = (const uint8_t *)flash_ptr;
while (size > ROW_SIZE) {
erase(ptr);
ptr += ROW_SIZE;
size -= ROW_SIZE;
}
erase(ptr);
}
void FlashClass::erase(const volatile void *flash_ptr)
{
#if defined(__SAMD51__)
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr);
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
while (!NVMCTRL->INTFLAG.bit.DONE) { }
invalidate_CMCC_cache();
#else
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
while (!NVMCTRL->INTFLAG.bit.READY) { }
#endif
}
void FlashClass::read(const volatile void *flash_ptr, void *data, uint32_t size)
{
memcpy(data, (const void *)flash_ptr, size);
}
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
Written by Cristian Maglie
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
// Concatenate after macro expansion
#define PPCAT_NX(A, B) A ## B
#define PPCAT(A, B) PPCAT_NX(A, B)
#if defined(__SAMD51__)
#define Flash(name, size) \
__attribute__((__aligned__(8192))) \
static const uint8_t PPCAT(_data,name)[(size+8191)/8192*8192] = { }; \
FlashClass name(PPCAT(_data,name), size);
#define FlashStorage(name, T) \
__attribute__((__aligned__(8192))) \
static const uint8_t PPCAT(_data,name)[(sizeof(T)+8191)/8192*8192] = { }; \
FlashStorageClass<T> name(PPCAT(_data,name));
#else
#define Flash(name, size) \
__attribute__((__aligned__(256))) \
static const uint8_t PPCAT(_data,name)[(size+255)/256*256] = { }; \
FlashClass name(PPCAT(_data,name), size);
#define FlashStorage(name, T) \
__attribute__((__aligned__(256))) \
static const uint8_t PPCAT(_data,name)[(sizeof(T)+255)/256*256] = { }; \
FlashStorageClass<T> name(PPCAT(_data,name));
#endif
class FlashClass {
public:
FlashClass(const void *flash_addr = NULL, uint32_t size = 0);
void write(const void *data) { write(flash_address, data, flash_size); }
void erase() { erase(flash_address, flash_size); }
void read(void *data) { read(flash_address, data, flash_size); }
void write(const volatile void *flash_ptr, const void *data, uint32_t size);
void erase(const volatile void *flash_ptr, uint32_t size);
void read(const volatile void *flash_ptr, void *data, uint32_t size);
private:
void erase(const volatile void *flash_ptr);
const uint32_t PAGE_SIZE, PAGES, MAX_FLASH, ROW_SIZE;
const volatile void *flash_address;
const uint32_t flash_size;
};
template<class T>
class FlashStorageClass {
public:
FlashStorageClass(const void *flash_addr) : flash(flash_addr, sizeof(T)) { };
// Write data into flash memory.
// Compiler is able to optimize parameter copy.
inline void write(T data) { flash.erase(); flash.write(&data); }
// Read data from flash into variable.
inline void read(T *data) { flash.read(data); }
// Overloaded version of read.
// Compiler is able to optimize copy-on-return.
inline T read() { T data; read(&data); return data; }
private:
FlashClass flash;
};
......@@ -823,4 +823,53 @@ so that should be OK, I'm writing at 0x1... tho this program uses 42kb, but inde
I don't know what is real anymore, the libraries failed me, the datasheet is opaque AF, I am writing somewhere I shouldn't, etc. Might be time to bring out the atmel studio guns.
Or the small guns: I'm going to try to get a minimum viable something up with this library.
\ No newline at end of file
Or the small guns: I'm going to try to get a minimum viable something up with this library.
Works like this:
```cpp
FlashStorage(flash_store, float);
void flash_write_init(void){
}
void flash_write_value(float val){
flash_store.write(val);
}
void Step_CL::print_table(void){
for(uint16_t e = 0; e < 4; e ++){
float ra = flash_store.read();
sysError("e: " + String(e) + " ra: " + String(ra, 4));
delay(5);
}
}
```
So I can try doing batches of these... Seems like a full 'page' works, I wonder if anything > 512 bytes does as well, or crashes... breaks at 256 floats, but not at 129...
So it seems that it should work, if I can get into the lower levels of this thing and increment pointers around. I'll try to do that first with just the 128 bytes that I know can work, and I'm pretty sure that's inside of one page.
OK, trips at the erase. Takes *forever* to reload code once I cripple it like this.
Oy, seems like I wrote it... then it dissappears after a reset, wth? That was to do with a volatile flag.
I think this has to do with erase block / instead of erase page. I should learn more about that in the data sheet.
Blocks are 16 pages: erase granularity is per block, write granularity is per page. One guess is that if the block / page are not aligned to a block, the EB command fails. Altho from 25.6.6.6 (fitting), it notes that any address within the block is valid for an erase block command.
OK, trying to unlock the block beforehand.
SO! Definitely hung on trying to erase a block. However, have had some evidence that this worked previously.
It's 1230 - I'll think about this tomorrow. Maybe try taking the above single-float working example apart, see if you can code it up yourself, to understand what's up.
## 2020 10 14
OK, today will bring this library into the local build and see about figuring what the heck it does, build the minimum example from scratch, and then see if I can scale that up to multiple blocks / tables.
- pages are 512 bytes
- blocks are 16 pages
This means a block is 8192, makes sense this is where flashstorage aligns itself. I need 8 blocks total for the full LUT.
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment