mirror of
https://github.com/synthetos/g2.git
synced 2026-09-23 12:14:09 +08:00
Get SD card working (includes motate ref update)
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -53,6 +53,7 @@ endif
|
||||
ifeq ("$(CONFIG)","MiniMill")
|
||||
ifeq ("$(BOARD)","NONE")
|
||||
BOARD=g2v9k
|
||||
BANTAM=1
|
||||
endif
|
||||
SETTINGS_FILE="settings_minimill.h"
|
||||
endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user