VERY rough initial work on modular boards layout

This commit is contained in:
Josh Stewart 2019-01-17 20:47:19 +11:00
parent c431caeafa
commit 750d486276
15 changed files with 400 additions and 14 deletions

1
.gitignore vendored
View File

@ -22,3 +22,4 @@ reference/hardware/v0.4/gerbers/Archive.zip
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/.browse.c_cpp.db*
speeduino/src/boards/samd21.h

View File

@ -44,7 +44,17 @@ framework = arduino
board = bluepill_f103c8
lib_deps = EEPROM
;build_flags = -fpermissive -std=gnu++11 -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,-Map,output.map
build_flags = -fpermissive -std=gnu++11 -Os
build_flags = -fpermissive -std=gnu++11 -Os
;SAMD21
[env:samd21]
platform = atmelsam
framework = arduino
board = zeroUSB
lib_deps = EEPROM
build_flags = -fpermissive -std=gnu++11
upload_protocol = sam-ba
;Support for the stm32f407 doesn't look ready in platformio yet
;[env:genericSTM32F407VE]

View File

@ -11,7 +11,6 @@ A full copy of the license may be found in the projects root directory
#include "maths.h"
#include "utils.h"
#include "decoders.h"
#include <EEPROM.h>
/*
Processes the data on the serial buffer.
@ -1406,7 +1405,8 @@ void receiveCalibration(byte tableID)
//From TS3.x onwards, the EEPROM must be written here as TS restarts immediately after the process completes which is before the EEPROM write completes
int y = EEPROM_START + (x / 2);
EEPROM.update(y, (byte)tempValue);
//EEPROM.update(y, (byte)tempValue);
storeCalibrationValue(y, (byte)tempValue);
every2nd = false;
#if defined(CORE_STM32)

View File

@ -51,6 +51,9 @@
#define portOutputRegister(port) (volatile byte *)( &(port->regs->ODR) )
#define portInputRegister(port) (volatile byte *)( &(port->regs->IDR) )
#endif
#elif defined(__SAMD21G18A__)
#define BOARD_H "src/boards/samd21.h"
#define CORE_SAMD21
#else
#error Incorrect board selected. Please select the correct board (Usually Mega 2560) and upload again
#endif

View File

@ -13,7 +13,6 @@
#include "decoders.h"
#include "corrections.h"
#include "idle.h"
#include <EEPROM.h>
void initialiseAll()
{
@ -155,8 +154,9 @@ void initialiseAll()
//barometric reading can be taken from either an external sensor if enabled, or simply by using the initial MAP value
if ( configPage6.useExtBaro != 0 )
{
readBaro();
EEPROM.update(EEPROM_LAST_BARO, currentStatus.baro);
readBaro();
//EEPROM.update(EEPROM_LAST_BARO, currentStatus.baro);
storeLastBaro(currentStatus.baro);
}
else
{
@ -168,13 +168,15 @@ void initialiseAll()
if ((currentStatus.MAP >= BARO_MIN) && (currentStatus.MAP <= BARO_MAX)) //Check if engine isn't running
{
currentStatus.baro = currentStatus.MAP;
EEPROM.update(EEPROM_LAST_BARO, currentStatus.baro);
//EEPROM.update(EEPROM_LAST_BARO, currentStatus.baro);
storeLastBaro(currentStatus.baro);
}
else
{
//Attempt to use the last known good baro reading from EEPROM
if ((EEPROM.read(EEPROM_LAST_BARO) >= BARO_MIN) && (EEPROM.read(EEPROM_LAST_BARO) <= BARO_MAX)) //Make sure it's not invalid (Possible on first run etc)
{ currentStatus.baro = EEPROM.read(EEPROM_LAST_BARO); } //last baro correction
//if (EEPROM.read(EEPROM_LAST_BARO) >= BARO_MIN) && (EEPROM.read(EEPROM_LAST_BARO) <= BARO_MAX)) //Make sure it's not invalid (Possible on first run etc)
if ((readLastBaro() >= BARO_MIN) && (readLastBaro() <= BARO_MAX)) //Make sure it's not invalid (Possible on first run etc)
{ currentStatus.baro = readLastBaro(); } //last baro correction
else { currentStatus.baro = 100; } //Final fall back position.
}
}

View File

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "storage.h"
#include "crankMaths.h"
#include "init.h"
#include BOARD_H //Note that this is not a real file, it is defined in globals.h.
#if defined (CORE_TEENSY)
#include <FlexCAN.h>
#endif

View File

@ -31,7 +31,7 @@
#define FastCRC_tables
#include "inttypes.h"
#if defined(__AVR__) || defined(STM32_MCU_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(_VARIANT_ARDUINO_STM32_)
#if defined(__AVR__) || defined(STM32_MCU_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(_VARIANT_ARDUINO_STM32_) || defined(__SAMD21G18A__)
#include <avr/pgmspace.h>
#else
#include <pgmspace.h>

View File

@ -0,0 +1,75 @@
/*
EEPROM like API that uses Arduino Zero's flash memory.
Written by A. Christian
Copyright (c) 2015-2016 Arduino LLC. All right reserved.
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
*/
#if defined(CORE_SAMD21)
#include "FlashAsEEPROM.h"
FlashStorage(eeprom_storage, EEPROM_EMULATION);
EEPROMClass::EEPROMClass(void) : _initialized(false), _dirty(false) {
// Empty
}
uint8_t EEPROMClass::read(int address)
{
if (!_initialized) init();
return _eeprom.data[address];
}
void EEPROMClass::update(int address, uint8_t value)
{
if (!_initialized) init();
if (_eeprom.data[address] != value) {
_dirty = true;
_eeprom.data[address] = value;
}
}
void EEPROMClass::write(int address, uint8_t value)
{
update(address, value);
}
void EEPROMClass::init()
{
_eeprom = eeprom_storage.read();
if (!_eeprom.valid) {
memset(_eeprom.data, 0xFF, EEPROM_EMULATION_SIZE);
}
_initialized = true;
}
bool EEPROMClass::isValid()
{
if (!_initialized) init();
return _eeprom.valid;
}
void EEPROMClass::commit()
{
if (!_initialized) init();
if (_dirty) {
_eeprom.valid = true;
eeprom_storage.write(_eeprom);
}
}
EEPROMClass EEPROM;
#endif

View File

@ -0,0 +1,87 @@
/*
EEPROM like API that uses Arduino Zero's flash memory.
Written by A. Christian
Copyright (c) 2015-2016 Arduino LLC. All right reserved.
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
*/
#ifndef FLASH_AS_EEPROM_h
#define FLASH_AS_EEPROM_h
#include "FlashStorage.h"
#ifndef EEPROM_EMULATION_SIZE
#define EEPROM_EMULATION_SIZE 1024
#endif
typedef struct {
byte data[EEPROM_EMULATION_SIZE];
boolean valid;
} EEPROM_EMULATION;
class EEPROMClass {
public:
EEPROMClass(void);
/**
* Read an eeprom cell
* @param index
* @return value
*/
uint8_t read(int);
/**
* Write value to an eeprom cell
* @param index
* @param value
*/
void write(int, uint8_t);
/**
* Update a eeprom cell
* @param index
* @param value
*/
void update(int, uint8_t);
/**
* Check whether the eeprom data is valid
* @return true, if eeprom data is valid (has been written at least once), false if not
*/
bool isValid();
/**
* Write previously made eeprom changes to the underlying flash storage
* Use this with care: Each and every commit will harm the flash and reduce it's lifetime (like with every flash memory)
*/
void commit();
uint16_t length() { return EEPROM_EMULATION_SIZE; }
private:
void init();
bool _initialized;
EEPROM_EMULATION _eeprom;
bool _dirty;
};
extern EEPROMClass EEPROM;
#endif

View File

@ -0,0 +1,102 @@
/*
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
*/
#if defined(CORE_SAMD21)
#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),
ROW_SIZE(PAGE_SIZE * 4),
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;
}
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
NVMCTRL->CTRLB.bit.MANW = 1;
// Do writes in pages
while (size) {
// Execute "PBC" Page Buffer Clear
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
// 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
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
}
}
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)
{
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
while (!NVMCTRL->INTFLAG.bit.READY) { }
}
void FlashClass::read(const volatile void *flash_ptr, void *data, uint32_t size)
{
memcpy(data, (const void *)flash_ptr, size);
}
#endif

View File

@ -0,0 +1,77 @@
/*
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)
#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));
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;
};

View File

View File

@ -1,12 +1,21 @@
#ifndef STORAGE_H
#define STORAGE_H
#include "globals.h"
void writeAllConfig();
void writeConfig(byte);
void loadConfig();
void loadCalibration();
void writeCalibration();
//These are utility functions that prevent other files from having to use EEPROM.h directly
byte readLastBaro();
void storeLastBaro(byte);
void storeCalibrationValue(byte, byte);
byte readEEPROMVersion();
void storeEEPROMVersion(byte);
#if defined(CORE_STM32) || defined(CORE_TEENSY)
#define EEPROM_MAX_WRITE_BLOCK 64 //The maximum number of write operations that will be performed in one go. If we try to write to the EEPROM too fast (Each write takes ~3ms) then the rest of the system can hang)
#else

View File

@ -8,7 +8,11 @@ A full copy of the license may be found in the projects root directory
#include "globals.h"
#include "table.h"
#include "comms.h"
#if defined(CORE_SAMD21)
#include "src/FlashStorage/FlashAsEEPROM.h"
#else
#include <EEPROM.h>
#endif
void writeAllConfig()
{
@ -643,3 +647,11 @@ void writeCalibration()
}
}
// Utility functions.
// By having these in this file, it prevents other files from calling EEPROM functions directly. This is useful due to differences in the EEPROM libraries on different devces
byte readLastBaro() { return EEPROM.read(EEPROM_LAST_BARO); }
void storeLastBaro(byte newValue) { EEPROM.update(EEPROM_LAST_BARO, newValue); }
void storeCalibrationValue(byte location, byte value) { EEPROM.update(location, value); } //This is essentially just an abstraction for EEPROM.update()
byte readEEPROMVersion() { return EEPROM.read(EEPROM_DATA_VERSION); }
void storeEEPROMVersion(byte newVersion) { EEPROM.update(EEPROM_DATA_VERSION, newVersion); }

View File

@ -4,9 +4,13 @@
* It also can be used for setting good values when there are viarables that move locations in the ini
* When a user skips multiple firmware versions at a time, this will roll through the updates 1 at a time
*/
#include <EEPROM.h>
#include "globals.h"
#include "storage.h"
#if defined(CORE_SAMD21)
#include "src/FlashStorage/FlashAsEEPROM.h"
#else
#include <EEPROM.h>
#endif
void doUpdates()
{
@ -23,7 +27,8 @@ void doUpdates()
}
}
writeAllConfig();
EEPROM.write(EEPROM_DATA_VERSION, 3);
//EEPROM.write(EEPROM_DATA_VERSION, 3);
storeEEPROMVersion(3);
}
//June 2017 required the forced addition of some CAN values to avoid weird errors
if(EEPROM.read(EEPROM_DATA_VERSION) == 3)
@ -36,7 +41,8 @@ void doUpdates()
if(configPage4.sparkDur == 255) { configPage4.sparkDur = 10; }
writeAllConfig();
EEPROM.write(EEPROM_DATA_VERSION, 4);
//EEPROM.write(EEPROM_DATA_VERSION, 4);
storeEEPROMVersion(4);
}
//July 2017 adds a cranking enrichment curve in place of the single value. This converts that single value to the curve
if(EEPROM.read(EEPROM_DATA_VERSION) == 4)
@ -53,7 +59,8 @@ void doUpdates()
configPage10.crankingEnrichValues[3] = 100 + configPage2.crankingPct;
writeAllConfig();
EEPROM.write(EEPROM_DATA_VERSION, 5);
//EEPROM.write(EEPROM_DATA_VERSION, 5);
storeEEPROMVersion(5);
}
//September 2017 had a major change to increase the minimum table size to 128. This required multiple pieces of data being moved around
if(EEPROM.read(EEPROM_DATA_VERSION) == 5)