Get SD card working (includes motate ref update)

This commit is contained in:
Rob Giseburt
2020-01-10 19:25:10 -06:00
parent 571a284656
commit 13d23b45b6
9 changed files with 217 additions and 167 deletions
+3 -8
View File
@@ -33,11 +33,11 @@
#include "controller.h"
#include "text_parser.h"
#include "board_xio.h"
#include "sd_card.h"
#include "MotateUtilities.h"
#include "MotateUniqueID.h"
#include "MotatePower.h"
#include "board_spi.h"
/*
* hardware_init() - lowest level hardware init
@@ -45,13 +45,8 @@
SPIBus_used_t spiBus;
extern SDCard<SPIBus_used_t::SPIBusDevice> sd_card;
SDCard<SPIBus_used_t::SPIBusDevice> sd_card {
spiBus,
Motate::SPIChipSelectPin<Motate::kSD_ChipSelectPinNumber>{}
};
Motate::SPIChipSelectPin<Motate::kSD_ChipSelectPinNumber> sdcs{};
SDCard_used_t sd_card{spiBus, sdcs};
void hardware_init()
{
+42
View File
@@ -0,0 +1,42 @@
/*
* * gpio.h - SPI definitions for this board
* For: /board/g2v9
* This file is part of the g2core project
*
* Copyright (c) 2019 Robert Giseburt
*
* This file ("the software") is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 as published by the
* Free Software Foundation. You should have received a copy of the GNU General Public
* License, version 2 along with the software. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, you may use this file as part of a software library without
* restriction. Specifically, if other files instantiate templates or use macros or
* inline functions from this file, or you compile this file and link it with other
* files to produce an executable, this file does not by itself cause the resulting
* executable to be covered by the GNU General Public License. This exception does not
* however invalidate any other reasons why the executable file might be covered by the
* GNU General Public License.
*
* THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef BOARD_SPI_H_ONCE
#define BOARD_SPI_H_ONCE
#include "MotateSPI.h"
#include "sd_card.h"
/**** SPI Setup ****/
typedef Motate::SPIBus<Motate::kSPI_MISOPinNumber, Motate::kSPI_MOSIPinNumber, Motate::kSPI_SCKPinNumber> SPIBus_used_t;
extern SPIBus_used_t spiBus;
typedef SDCard<SPIBus_used_t::SPIBusDevice, Motate::SPIChipSelectPin<Motate::kSD_ChipSelectPinNumber>> SDCard_used_t;
extern SDCard_used_t sd_card;
#endif // BOARD_SPI_H_ONCE
+1 -9
View File
@@ -60,8 +60,8 @@
*************************/
#include "MotatePins.h"
#include "MotateSPI.h"
#include "MotateTimers.h" // for TimerChanel<> and related...
#include "MotateUtilities.h" // for TimerChanel<> and related...
using Motate::TimerChannel;
@@ -119,14 +119,6 @@ typedef TimerChannel<5,0> fwd_plan_timer_type; // request exec timer in stepper.
pin_number indicator_led_pin_num = Motate::kLED_USBRXPinNumber;
static PWMOutputPin<indicator_led_pin_num> IndicatorLed;
/**** SPI Setup ****/
typedef Motate::SPIBus<Motate::kSPI_MISOPinNumber, Motate::kSPI_MOSIPinNumber, Motate::kSPI_SCKPinNumber> SPIBus_used_t;
extern SPIBus_used_t spiBus;
// typedef Motate::SPIChipSelectPinMux<Motate::kSocket1_SPISlaveSelectPinNumber, Motate::kSocket2_SPISlaveSelectPinNumber, Motate::kSocket3_SPISlaveSelectPinNumber, Motate::kSocket4_SPISlaveSelectPinNumber> SPI_CS_PinMux_used_t;
// extern SPI_CS_PinMux_used_t spiCSPinMux;
/**** Motate Global Pin Allocations ****/
//static OutputPin<kSocket1_SPISlaveSelectPinNumber> spi_ss1_pin;
+1
View File
@@ -53,6 +53,7 @@ endif
ifeq ("$(CONFIG)","MiniMill")
ifeq ("$(BOARD)","NONE")
BOARD=g2v9k
BANTAM=1
endif
SETTINGS_FILE="settings_minimill.h"
endif
+66 -67
View File
@@ -4,16 +4,15 @@
#include <stdio.h>
#include <memory>
// SD Card
extern SDCard<SPIBus_used_t::SPIBusDevice> sd_card;
#include "board_spi.h"
// Card Detect Pin
Motate::InputPin<Motate::kSD_CardDetectPinNumber> cdPin;
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
static volatile
@@ -34,20 +33,20 @@ int rcvr_datablock ( /* 1:OK, 0:Failed */
)
{
volatile INT token;
uint32_t start = Motate::SysTickTimer.getValue();
do { /* Wait for data packet in timeout of 100ms */
token = sd_card.read(SPIMessage::DeassertAfter, 0xFF);
token = sd_card.read(SPIMessage::DeassertAfter);
} while ((token != 0xFE) && Motate::SysTickTimer.getValue()-start < 100);
if(token != 0xFE) {
return 0; /* If not valid data token, return with error */
}
sd_card.read((uint8_t*)buff, btr);
sd_card.read(SPIMessage::RemainAsserted, 0xFF); /* Discard CRC */
sd_card.read(SPIMessage::RemainAsserted, 0xFF);
sd_card.read(SPIMessage::RemainAsserted); /* Discard CRC */
sd_card.read(SPIMessage::RemainAsserted);
return 1; /* Return with success */
}
@@ -67,9 +66,9 @@ int xmit_datablock ( /* 1:OK, 0:Failed */
BYTE resp = 0;
BYTE *buff_temp = (BYTE *)buff; //ms: fix
bool stop = (token == 0xFD);
sd_card.write(token, stop); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
sd_card.write(buff_temp, 512);
sd_card.write(0xFF); /* CRC (Dummy) */
@@ -77,15 +76,15 @@ int xmit_datablock ( /* 1:OK, 0:Failed */
do {
resp = sd_card.read() & 0x1F; /* Receive data response */
} while (resp == 0 || resp == 0x1F);
if (resp != 0x05) /* If not accepted, return with error */
return 0;
if (resp != 0x05) /* If not accepted, return with error */
return 0;
}
return 1;
}
#endif
alignas(4) uint8_t data[6];
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
@@ -106,37 +105,37 @@ uint8_t send_cmd ( /* Returns command response (bit7==1:Send failed)*/
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
// wait until card is ready to receive command
uint32_t start = Motate::SysTickTimer.getValue();
while ((sd_card.read(SPIMessage::DeassertAfter, 0xFF) != 0xFF) && Motate::SysTickTimer.getValue() - start < 1000) {};
Motate::Timeout timeout;
timeout.set(1000);
while ((sd_card.read(SPIMessage::DeassertAfter) != 0xFF) && !timeout.isPast()) {};
// choose the command CRC
uint8_t n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
// send command packet
uint8_t data[6] = {
(uint8_t)(0x40 | cmd),
(uint8_t)((arg >> 24) & 0xFF),
(uint8_t)((arg >> 16) & 0xFF),
(uint8_t)((arg >> 8) & 0xFF),
(uint8_t)(arg & 0xFF),
n
};
data[0] = (0x40 | cmd);
data[1] = ((arg >> 24) & 0xFF);
data[2] = ((arg >> 16) & 0xFF);
data[3] = ((arg >> 8) & 0xFF);
data[4] = (arg & 0xFF);
data[5] = n;
sd_card.write(data, 6, SPIMessage::RemainAsserted);
// receive response
if (cmd == CMD12) sd_card.read(SPIMessage::RemainAsserted, 0xFF); /* Skip a stuff byte when stop reading */
if (cmd == CMD12) sd_card.read(SPIMessage::RemainAsserted); /* Skip a stuff byte when stop reading */
uint8_t tries = 0xFF; /* Wait for a valid response in timeout of 10 attempts */
do
res = sd_card.read(SPIMessage::RemainAsserted, 0xFF);
res = sd_card.read(SPIMessage::RemainAsserted);
while ((res & 0x80) && --tries); // 7th bit is low in all valid responses
if (ocr)
sd_card.read(ocr, 4);
return res; /* Return with the response value */
}
@@ -147,7 +146,7 @@ uint8_t send_cmd_until_specific_response(uint8_t command, uint32_t args, uint8_t
do {
resp = send_cmd(command, args, ocr);
} while (resp != response && attempts--);
return (resp == response);
}
@@ -160,16 +159,16 @@ DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0) */
)
{
BYTE n, ty, cmd, ocr[4];
BYTE ty, cmd, ocr[4];
if (drv) return STA_NOINIT; /* Supports only single drive */
if (disk_status(drv) & STA_NODISK) return Stat; /* No card in the socket */
// initialization has to be performed at a slower speed
sd_card.setOptions(SD_INIT_SPEED);
for (n = 10; n; n--) sd_card.read(); /* 80 dummy clocks */
sd_card.setSDMode(); /* 80 dummy clocks */
ty = 0;
if (send_cmd_until_specific_response(CMD0, 0, 1)) { /* Enter Idle state */
if (send_cmd(CMD8, 0x1AA, &ocr[0]) == 1) { /* SDv2? */
@@ -196,13 +195,13 @@ DSTATUS disk_initialize (
}
}
CardType = ty;
if (ty) { /* Initialization succeeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
}
sd_card.setOptions(SD_ACTIVE_SPEED);
return Stat;
}
@@ -216,7 +215,7 @@ DSTATUS disk_status (
)
{
if (drv != SD0) return STA_NOINIT;
if (cdPin.getInputValue()) {
Stat = STA_NODISK | STA_NOINIT;
} else {
@@ -242,12 +241,12 @@ DRESULT disk_read (
{
if (drv || !count) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
BYTE cmd;
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
if (send_cmd_until_specific_response(cmd, sector, 0)) {
do {
if (!rcvr_datablock(buff, 512)) break;
@@ -255,7 +254,7 @@ DRESULT disk_read (
} while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
return count ? RES_ERROR : RES_OK;
}
@@ -274,12 +273,12 @@ DRESULT disk_write (
)
{
if (drv || !count) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if (send_cmd_until_specific_response(CMD24, sector, 0)
&& xmit_datablock(buff, 0xFE))
@@ -296,7 +295,7 @@ DRESULT disk_write (
count = 1;
}
}
return count ? RES_ERROR : RES_OK;
}
#endif
@@ -316,17 +315,17 @@ DRESULT disk_ioctl (
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE*)buff;
DWORD cs;
if (drv) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
res = RES_ERROR;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process */
res = RES_OK;
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
@@ -340,7 +339,7 @@ DRESULT disk_ioctl (
res = RES_OK;
}
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
if (CardType & CT_SD2) { /* SDv2 */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
@@ -362,30 +361,30 @@ DRESULT disk_ioctl (
}
}
break;
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
*ptr = CardType;
res = RES_OK;
break;
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (send_cmd(CMD58, 0, ptr) == 0) { /* READ_OCR */
res = RES_OK;
}
break;
case MMC_GET_SDSTAT : /* Receive SD status as a data block (64 bytes) */
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
sd_card.read();
@@ -393,13 +392,13 @@ DRESULT disk_ioctl (
res = RES_OK;
}
break;
default:
res = RES_PARERR;
}
// deselect();
return res;
}
#endif
+4 -2
View File
@@ -17,6 +17,8 @@
#ifndef _FATFS
#define _FATFS 80376 /* Revision ID */
#include <stdalign.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -119,7 +121,7 @@ typedef struct {
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
alignas(4) BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
@@ -147,7 +149,7 @@ typedef struct {
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
alignas(4) BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
+65 -47
View File
@@ -10,6 +10,8 @@
#ifndef sd_card_h
#define sd_card_h
#include "MotateSPI.h"
using Motate::SPIMessage;
using Motate::SPIInterrupt;
using Motate::SPIDeviceMode;
@@ -17,7 +19,7 @@ using Motate::SPIDeviceMode;
/* Definitions */
#define SCRIBBLE_BUF_MAX 10 // Maximum number of bytes expected for toss
template <typename device_t>
template <typename device_t, typename chipSelect_t>
struct SDCard final {
private:
// SPI and message handling properties
@@ -34,20 +36,20 @@ struct SDCard final {
// Timer to keep track of when we need to do another periodic update
Motate::Timeout check_timer;
public:
chipSelect_t &_chip_select;
public:
// Primary constructor - templated to take any SPIBus and chipSelect type
template <typename SPIBus_t, typename chipSelect_t>
SDCard(SPIBus_t &spi_bus, const chipSelect_t &_cs)
: _device{spi_bus.getDevice(_cs, // pass it the chipSelect
4000000,
SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit,
0, // min_between_cs_delay_ns
0, // cs_to_sck_delay_ns
0 // between_word_delay_ns
)}
{
init();
};
template <typename SPIBus_t>
SDCard(SPIBus_t &spi_bus, chipSelect_t &chip_select)
: _device{spi_bus.getDevice(chip_select, // pass it the chip select
100000, SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit,
400, // min_between_chip_select_delay_ns
400, // cs_to_sck_delay_ns
80 // between_word_delay_ns
)},
_chip_select{chip_select}
{ init(); };
// Allow the default move constructor
SDCard(SDCard &&other) = default;
@@ -57,11 +59,11 @@ struct SDCard final {
// Toss out buffer
uint8_t _scribble_buffer[SCRIBBLE_BUF_MAX];
uint8_t _out_buffer[512];
bool _spi_write = false;
bool _spi_read = false;
bool _deassert_cs = false;
uint8_t _send_as_noop = 0x0;
bool _deassert_chip_select = SPIMessage::DeassertAfter;
uint16_t _num_bytes = 0;
uint8_t *_spi_data;
@@ -72,19 +74,14 @@ struct SDCard final {
_transmitting = true; // preemptively say we're transmitting .. as a mutex
// We write before we read -- so we don't lose what we set in the registers when writing
if (_spi_write) {
if (_spi_write) {
_spi_write = false;
_message.setup(_spi_data, _scribble_buffer, _num_bytes, _deassert_cs, SPIMessage::EndTransaction);
_message.setup(_spi_data, nullptr, _num_bytes, _deassert_chip_select, SPIMessage::EndTransaction);
} else if (_spi_read) {
_spi_read = false;
// Populate scribble buffer with no op bytes
for (int i = 0; i < _num_bytes; i++) {
_scribble_buffer[i] = _send_as_noop;
}
_message.setup(_scribble_buffer, _spi_data, _num_bytes, _deassert_cs, SPIMessage::EndTransaction);
_message.setup(nullptr, _spi_data, _num_bytes, _deassert_chip_select, SPIMessage::EndTransaction);
// otherwise we're done here
} else {
@@ -100,16 +97,33 @@ struct SDCard final {
// Establish default values
_spi_write = false;
_spi_read = false;
_deassert_cs = false;
_send_as_noop = 0x0;
_deassert_chip_select = false;
_num_bytes = 0;
// mark that init has finished and set the timer
_inited = true;
}
void setSDMode() {
// _device._spi_bus->misoPin.setOptions(Motate::kPullUp);
for (size_t i = 100000; i--;) {
/* code */
}
const auto cs_mode = _chip_select.getMode();
_chip_select.setMode(Motate::kOutput);
_chip_select.set();
// _device._spi_bus->misoPin.setMode(Motate::kOutput);
// _device._spi_bus->misoPin.set();
alignas(4) uint8_t tossme[12];
this->read(tossme, 10); /* 80 dummy clocks */
_chip_select.setMode(cs_mode);
// _device._spi_bus->misoPin.setOptions(Motate::kNormal);
};
void setOptions(const uint32_t baud, const uint16_t options = (SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit), uint32_t min_between_cs_delay_ns = 0, uint32_t cs_to_sck_delay_ns = 0, uint32_t between_word_delay_ns = 0) {
_device.setOptions(baud, options, min_between_cs_delay_ns, cs_to_sck_delay_ns, between_word_delay_ns);
void setOptions(const uint32_t baud, const uint16_t options = (SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit), uint32_t min_between_chip_select_delay_ns = 400, uint32_t cs_to_sck_delay_ns = 400, uint32_t between_word_delay_ns = 80) {
_device.setOptions(baud, options, min_between_chip_select_delay_ns, cs_to_sck_delay_ns, between_word_delay_ns);
}
void messageDoneCallback() {
@@ -120,54 +134,58 @@ struct SDCard final {
_startNextReadWrite();
};
void read(uint8_t *data, const uint16_t num_bytes, const bool deassert_cs = SPIMessage::RemainAsserted, const uint8_t send_as_noop = 0x0) {
void read(uint8_t *data, const uint16_t num_bytes, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
// Configure multi byte read
_spi_read = true;
_spi_data = data;
_deassert_cs = deassert_cs;
_send_as_noop = send_as_noop;
_deassert_chip_select = deassert_chip_select;
_num_bytes = num_bytes;
// Set up read
_startNextReadWrite();
while (_transmitting) {
;
}
};
uint8_t read(const bool deassert_cs = SPIMessage::RemainAsserted, const uint8_t send_as_noop = 0x0) {
uint8_t data[1] = {0x00};
uint8_t read(const bool deassert_chip_select = SPIMessage::DeassertAfter) {
// Configure and set up single byte read
read(data, 1, deassert_cs, send_as_noop);
return data[0];
read(_scribble_buffer, 1, deassert_chip_select);
return _scribble_buffer[0];
};
void write(uint8_t *data, const uint16_t num_bytes, const bool deassert_cs = SPIMessage::RemainAsserted) {
void write(uint8_t *data, const uint16_t num_bytes, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
// Configure multi byte write
_spi_write = true;
_spi_data = data;
_deassert_cs = deassert_cs;
_deassert_chip_select = deassert_chip_select;
_num_bytes = num_bytes;
// Set up write
_startNextReadWrite();
while (_transmitting) {
;
}
};
void write(uint8_t data, const bool deassert_cs = SPIMessage::RemainAsserted) {
void write(uint8_t data, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
_scribble_buffer[0] = data;
// Configure and set up single byte write
write(&data, 1, deassert_cs);
write(_scribble_buffer, 1, deassert_chip_select);
};
// this would be called by the project or from a SysTickHandler
void periodicCheck() {
if (!_inited || (check_timer.isSet() && !check_timer.isPast())) {
// not yet, too soon
return;
}
//TEMP
//uint8_t rd = 0x2;
//uint8_t noop = 0xA5;
+32 -18
View File
@@ -29,12 +29,26 @@
#include "canonical_machine.h"
#include "report.h"
#include "util.h"
#include "board_spi.h"
#include "ff.h"
/***********************************************************************************
**** STRUCTURE ALLOCATIONS ********************************************************
***********************************************************************************/
nvmSingleton_t nvm;
//**** persistence singleton ****
struct nvmSingleton_t {
float tmp_value;
FATFS fat_fs;
FIL file;
uint8_t file_index;
alignas(4) uint8_t io_buffer[IO_BUFFER_SIZE];
index_t changed_nv_indexes[MAX_WRITE_CHANGES];
uint16_t changed_nvs;
uint32_t last_write_systick;
uint8_t write_failures;
} nvm;
/***********************************************************************************
**** GENERIC STATIC FUNCTIONS AND VARIABLES ***************************************
@@ -129,7 +143,7 @@ stat_t write_persistent_value(nvObj_t *nv)
*/
stat_t write_persistent_values_callback()
{
{
// Check the disk status to ensure we catch card-detect pin changes.
// FIXME: it would be much better to do this with an interrupt!
f_polldisk();
@@ -137,7 +151,7 @@ stat_t write_persistent_values_callback()
if (Motate::SysTickTimer.getValue() - nvm.last_write_systick < MIN_WRITE_INTERVAL) return (STAT_NOOP);
// this check may not be necessary on ARM, but just in case...
if (cm->cycle_type != CYCLE_NONE) return(STAT_NOOP); // can't write when machine is moving
if(write_persistent_values() == STAT_OK) {
nvm.changed_nvs = 0;
nvm.write_failures = 0;
@@ -192,7 +206,7 @@ stat_t prepare_persistence_file()
// would slow down consecutive reads. However, we still need to re-validate before
// every use to ensure that the card status hasn't changed.
if (f_is_open(&nvm.file) && validate(&nvm.file) == FR_OK) return STAT_OK;
// mount volume if necessary
if (!nvm.fat_fs.fs_type) {
fs_ritorno(f_mount(&nvm.fat_fs, "", 1), "mount"); /* Give a work area to the default drive */
@@ -201,7 +215,7 @@ stat_t prepare_persistence_file()
uint8_t index = active_file_index();
fs_ritorno(f_open(&nvm.file, filenames[index], FA_READ | FA_OPEN_EXISTING), "open input");
nvm.file_index = index;
// if CRC doesn't match, delete file and return error
if (validate_persistence_file() != STAT_OK) {
f_close(&nvm.file);
@@ -217,7 +231,7 @@ stat_t prepare_persistence_file()
/*
* validate_persistence_file()
*
* ARM only. Helper function that checks the CRC and byte count of the
* ARM only. Helper function that checks the CRC and byte count of the
* persistence file. Assumes the file is already open.
*/
stat_t validate_persistence_file()
@@ -228,7 +242,7 @@ stat_t validate_persistence_file()
fs_ritorno(f_lseek(&nvm.file, 0), "crc check seek");
while (!f_eof(&nvm.file)) {
fs_ritorno(f_read(&nvm.file, &nvm.io_buffer, IO_BUFFER_SIZE, &br), "file read during CRC check");
if (f_eof(&nvm.file)) {
br -= std::min((UINT)CRC_LEN, br); // don't include old CRC in current CRC calculation
memcpy(&filecrc, nvm.io_buffer+br, CRC_LEN); // copy old CRC out of read buffer
@@ -237,7 +251,7 @@ stat_t validate_persistence_file()
crc = crc32(crc, nvm.io_buffer, br);
br_sum += br;
}
// how did we do?
if (br_sum != nv_index_max() * NVM_VALUE_LEN) {
DEBUG_PRINT("bad byte count in file: %i\n", br_sum);
@@ -249,7 +263,7 @@ stat_t validate_persistence_file()
/*
* write_persistent_values()
*
*
* ARM only. Writes all the values from the write cache to the SD card. Since we can't
* rewrite individual pieces of data in the middle of an existing file, this requires
* rewriting all the data into a new file.
@@ -257,7 +271,7 @@ stat_t validate_persistence_file()
stat_t write_persistent_values()
{
DEBUG_PRINT("writing new version\n");
FIL f_out;
UINT bw;
nvObj_t *nv = nv_reset_nv_list(); // sets *nv to the start of the body
@@ -271,12 +285,12 @@ stat_t write_persistent_values()
if (prepare_persistence_file() == STAT_OK) {
fs_ritorno(f_lseek(&nvm.file, 0), "f_lseek to input file start");
}
// open new file for writing updated values
fs_ritorno(f_open(&f_out, filenames[NEXT_FILE_INDEX], FA_WRITE | FA_OPEN_ALWAYS), "open output");
fs_ritorno(f_sync(&f_out), "sync output file");
DEBUG_PRINT("opened %s for writing\n", filenames[NEXT_FILE_INDEX]);
uint32_t crc = 0;
uint16_t step = IO_BUFFER_SIZE/NVM_VALUE_LEN;
@@ -286,7 +300,7 @@ stat_t write_persistent_values()
UINT br = 0;
f_read(&nvm.file, &nvm.io_buffer, io_byte_count, &br);
DEBUG_PRINT("read %i bytes from old file\n", br);
// if we didn't get enough bytes from the old file, pad the buffer with defaults
// to keep the length correct
// FIXME: integrate this with default-setting code in config.cpp
@@ -321,16 +335,16 @@ stat_t write_persistent_values()
changed_nvs_idx++;
}
}
// write updated values to output file and sync
fs_ritorno(f_write(&f_out, &nvm.io_buffer, io_byte_count, &bw), "new file write");
if (bw != io_byte_count) return (STAT_PERSISTENCE_ERROR);
fs_ritorno(f_sync(&f_out), "out sync");
// update CRC
crc = crc32(crc, nvm.io_buffer, io_byte_count);
}
// write CRC in final 4 bytes
fs_ritorno(f_write(&f_out, &crc, CRC_LEN, &bw), "write crc");
DEBUG_PRINT("wrote crc: %lu\n", crc);
@@ -345,8 +359,8 @@ stat_t write_persistent_values()
nvm.file_index = 0;
}
// Restore units mode
// Restore units mode
cm_set_distance_mode(saved_distance_mode);
return (STAT_OK);
}
}
+3 -16
View File
@@ -29,8 +29,8 @@
#define PERSISTENCE_H_ONCE
#include "config.h" // needed for nvObj_t definition
#include "ff.h"
#include "util.h" // FIXME: this won't compile if included after <map>
// #include "ff.h"
// #include "util.h" // FIXME: this won't compile if included after <map>
#define NVM_VALUE_LEN 4 // NVM value length (float, fixed length)
#define NVM_BASE_ADDR 0x0000 // base address of usable NVM
@@ -40,20 +40,6 @@
#define MAX_WRITE_FAILURES 3
#define MAX_WRITE_CHANGES IO_BUFFER_SIZE // maximum number of write values that change - ms: TODO
//**** persistence singleton ****
typedef struct nvmSingleton {
float tmp_value;
FATFS fat_fs;
FIL file;
uint8_t file_index;
uint8_t io_buffer[IO_BUFFER_SIZE];
index_t changed_nv_indexes[MAX_WRITE_CHANGES];
uint16_t changed_nvs;
uint32_t last_write_systick;
uint8_t write_failures;
} nvmSingleton_t;
//**** persistence function prototypes ****
void persistence_init(void);
@@ -62,3 +48,4 @@ stat_t write_persistent_value(nvObj_t *nv);
stat_t write_persistent_values_callback();
#endif // End of include guard: PERSISTENCE_H_ONCE
//