mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 11:29:58 +03:00
parent
66e83511c7
commit
3cd5de187a
5 changed files with 90 additions and 47 deletions
|
@ -209,6 +209,10 @@ void spiInternalStartDMA(const extDevice_t *dev)
|
||||||
dmaChannelDescriptor_t *dmaTx = dev->bus->dmaTx;
|
dmaChannelDescriptor_t *dmaTx = dev->bus->dmaTx;
|
||||||
dmaChannelDescriptor_t *dmaRx = dev->bus->dmaRx;
|
dmaChannelDescriptor_t *dmaRx = dev->bus->dmaRx;
|
||||||
DMA_ARCH_TYPE *streamRegsTx = (DMA_ARCH_TYPE *)dmaTx->ref;
|
DMA_ARCH_TYPE *streamRegsTx = (DMA_ARCH_TYPE *)dmaTx->ref;
|
||||||
|
|
||||||
|
// Wait for any ongoing transmission to complete
|
||||||
|
while (spi_i2s_flag_get(dev->bus->busType_u.spi.instance, SPI_I2S_BF_FLAG) == SET);
|
||||||
|
|
||||||
if (dmaRx) {
|
if (dmaRx) {
|
||||||
DMA_ARCH_TYPE *streamRegsRx = (DMA_ARCH_TYPE *)dmaRx->ref;
|
DMA_ARCH_TYPE *streamRegsRx = (DMA_ARCH_TYPE *)dmaRx->ref;
|
||||||
|
|
||||||
|
@ -230,10 +234,10 @@ void spiInternalStartDMA(const extDevice_t *dev)
|
||||||
xDMA_Init(streamRegsRx, dev->bus->initRx);
|
xDMA_Init(streamRegsRx, dev->bus->initRx);
|
||||||
|
|
||||||
// Enable streams
|
// Enable streams
|
||||||
xDMA_Cmd(streamRegsTx, TRUE);
|
|
||||||
xDMA_Cmd(streamRegsRx, TRUE);
|
xDMA_Cmd(streamRegsRx, TRUE);
|
||||||
|
xDMA_Cmd(streamRegsTx, TRUE);
|
||||||
|
|
||||||
/* Enable the receiver before the transmitter to ensure that not bits are missed on reception. An interrupt between
|
/* Enable the receiver before the transmitter to ensure that no bits are missed on reception. An interrupt between
|
||||||
* the transmitter and receiver being enabled can otherwise cause a hang.
|
* the transmitter and receiver being enabled can otherwise cause a hang.
|
||||||
*/
|
*/
|
||||||
spi_i2s_dma_receiver_enable(dev->bus->busType_u.spi.instance, TRUE);
|
spi_i2s_dma_receiver_enable(dev->bus->busType_u.spi.instance, TRUE);
|
||||||
|
|
|
@ -31,20 +31,23 @@
|
||||||
#if defined(STM32F4)
|
#if defined(STM32F4)
|
||||||
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
|
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
|
||||||
#define SPI_IO_AF_SCK_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_DOWN)
|
#define SPI_IO_AF_SCK_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_DOWN)
|
||||||
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP)
|
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP)
|
||||||
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
|
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
|
||||||
|
#define SPI_IO_CS_HIGH_CFG IO_CONFIG(GPIO_Mode_IN, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP)
|
||||||
#elif defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
|
#elif defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
|
||||||
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
|
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
|
||||||
#define SPI_IO_AF_SCK_CFG_HIGH IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
#define SPI_IO_AF_SCK_CFG_HIGH IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
||||||
#define SPI_IO_AF_SCK_CFG_LOW IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN)
|
#define SPI_IO_AF_SCK_CFG_LOW IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN)
|
||||||
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
||||||
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
|
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
|
||||||
|
#define SPI_IO_CS_HIGH_CFG IO_CONFIG(GPIO_MODE_INPUT, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
||||||
#elif defined(AT32F4)
|
#elif defined(AT32F4)
|
||||||
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL , GPIO_PULL_NONE)
|
#define SPI_IO_AF_CFG IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE)
|
||||||
#define SPI_IO_AF_SCK_CFG_HIGH IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL , GPIO_PULL_UP)
|
#define SPI_IO_AF_SCK_CFG_HIGH IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP)
|
||||||
#define SPI_IO_AF_SCK_CFG_LOW IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL , GPIO_PULL_DOWN)
|
#define SPI_IO_AF_SCK_CFG_LOW IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_DOWN)
|
||||||
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL , GPIO_PULL_UP)
|
#define SPI_IO_AF_SDI_CFG IO_CONFIG(GPIO_MODE_MUX, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP)
|
||||||
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL , GPIO_PULL_NONE)
|
#define SPI_IO_CS_CFG IO_CONFIG(GPIO_MODE_OUTPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE)
|
||||||
|
#define SPI_IO_CS_HIGH_CFG IO_CONFIG(GPIO_MODE_INPUT, GPIO_DRIVE_STRENGTH_STRONGER, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_UP)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// De facto standard mode
|
// De facto standard mode
|
||||||
|
|
|
@ -91,7 +91,7 @@ typedef struct sdcard_t {
|
||||||
|
|
||||||
#ifdef USE_SDCARD_SPI
|
#ifdef USE_SDCARD_SPI
|
||||||
extDevice_t dev;
|
extDevice_t dev;
|
||||||
uint8_t idleCount;
|
int8_t idleCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SDCARD_SDIO
|
#ifdef USE_SDCARD_SDIO
|
||||||
|
|
|
@ -112,7 +112,7 @@ static void sdcard_reset(void)
|
||||||
|
|
||||||
|
|
||||||
// Called in ISR context
|
// Called in ISR context
|
||||||
// Wait until idle indicated by a read value of 0xff
|
// Wait until idle indicated by a read value of SDCARD_IDLE_TOKEN
|
||||||
busStatus_e sdcard_callbackIdle(uint32_t arg)
|
busStatus_e sdcard_callbackIdle(uint32_t arg)
|
||||||
{
|
{
|
||||||
sdcard_t *sdcard = (sdcard_t *)arg;
|
sdcard_t *sdcard = (sdcard_t *)arg;
|
||||||
|
@ -120,11 +120,12 @@ busStatus_e sdcard_callbackIdle(uint32_t arg)
|
||||||
|
|
||||||
uint8_t idleByte = dev->bus->curSegment->u.buffers.rxData[0];
|
uint8_t idleByte = dev->bus->curSegment->u.buffers.rxData[0];
|
||||||
|
|
||||||
if (idleByte == 0xff) {
|
if (idleByte == SDCARD_IDLE_TOKEN) {
|
||||||
return BUS_READY;
|
// Default for next call to sdcard_callbackNotIdle()
|
||||||
|
sdcard->idleCount = SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY; return BUS_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (--sdcard->idleCount == 0) {
|
if (--sdcard->idleCount <= 0) {
|
||||||
dev->bus->curSegment->u.buffers.rxData[0] = 0x00;
|
dev->bus->curSegment->u.buffers.rxData[0] = 0x00;
|
||||||
return BUS_ABORT;
|
return BUS_ABORT;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +135,7 @@ busStatus_e sdcard_callbackIdle(uint32_t arg)
|
||||||
|
|
||||||
|
|
||||||
// Called in ISR context
|
// Called in ISR context
|
||||||
// Wait until idle is no longer indicated by a read value of 0xff
|
// Wait until idle is no longer indicated by a read value of SDCARD_IDLE_TOKEN
|
||||||
busStatus_e sdcard_callbackNotIdle(uint32_t arg)
|
busStatus_e sdcard_callbackNotIdle(uint32_t arg)
|
||||||
{
|
{
|
||||||
sdcard_t *sdcard = (sdcard_t *)arg;
|
sdcard_t *sdcard = (sdcard_t *)arg;
|
||||||
|
@ -142,11 +143,11 @@ busStatus_e sdcard_callbackNotIdle(uint32_t arg)
|
||||||
|
|
||||||
uint8_t idleByte = dev->bus->curSegment->u.buffers.rxData[0];
|
uint8_t idleByte = dev->bus->curSegment->u.buffers.rxData[0];
|
||||||
|
|
||||||
if (idleByte != 0xff) {
|
if (idleByte != SDCARD_IDLE_TOKEN) {
|
||||||
return BUS_READY;
|
return BUS_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdcard->idleCount-- == 0) {
|
if (sdcard->idleCount-- <= 0) {
|
||||||
return BUS_ABORT;
|
return BUS_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,11 +178,11 @@ static bool sdcard_waitForIdle(int maxBytesToWait)
|
||||||
// Block pending completion of SPI access
|
// Block pending completion of SPI access
|
||||||
spiWait(&sdcard.dev);
|
spiWait(&sdcard.dev);
|
||||||
|
|
||||||
return (idleByte == 0xff);
|
return (idleByte == SDCARD_IDLE_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for up to maxDelay 0xFF idle bytes to arrive from the card, returning the first non-idle byte found.
|
* Wait for up to maxDelay SDCARD_IDLE_TOKEN idle bytes to arrive from the card, returning the first non-idle byte found.
|
||||||
*
|
*
|
||||||
* Returns 0xFF on failure.
|
* Returns 0xFF on failure.
|
||||||
*/
|
*/
|
||||||
|
@ -211,9 +212,9 @@ static uint8_t sdcard_waitForNonIdleByte(int maxDelay)
|
||||||
* with the given argument, waits up to SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY bytes for a reply, and returns the
|
* with the given argument, waits up to SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY bytes for a reply, and returns the
|
||||||
* first non-0xFF byte of the reply.
|
* first non-0xFF byte of the reply.
|
||||||
*
|
*
|
||||||
* Upon failure, 0xFF is returned.
|
* Upon failure, -1 is returned.
|
||||||
*/
|
*/
|
||||||
static uint8_t sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
|
static int sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
|
||||||
{
|
{
|
||||||
uint8_t command[6] = {
|
uint8_t command[6] = {
|
||||||
0x40 | commandCode,
|
0x40 | commandCode,
|
||||||
|
@ -226,18 +227,17 @@ static uint8_t sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t idleByte;
|
uint8_t idleByte;
|
||||||
|
uint8_t cmdResponse;
|
||||||
|
|
||||||
// Note that this does not release the CS at the end of the transaction
|
// Note that this does not release the CS at the end of the transaction
|
||||||
busSegment_t segments[] = {
|
busSegment_t segments[] = {
|
||||||
|
{.u.buffers = {NULL, &idleByte}, sizeof(idleByte), false, sdcard_callbackIdle},
|
||||||
{.u.buffers = {command, NULL}, sizeof(command), false, NULL},
|
{.u.buffers = {command, NULL}, sizeof(command), false, NULL},
|
||||||
{.u.buffers = {NULL, &idleByte}, sizeof(idleByte), false, sdcard_callbackNotIdle},
|
{.u.buffers = {NULL, &cmdResponse}, sizeof(cmdResponse), false, sdcard_callbackNotIdle},
|
||||||
{.u.link = {NULL, NULL}, 0, true, NULL},
|
{.u.link = {NULL, NULL}, 0, true, NULL},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!sdcard_waitForIdle(SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY) && commandCode != SDCARD_COMMAND_GO_IDLE_STATE)
|
|
||||||
return 0xFF;
|
|
||||||
|
|
||||||
sdcard.idleCount = SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY;
|
sdcard.idleCount = SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY;
|
||||||
|
|
||||||
spiSequence(&sdcard.dev, &segments[0]);
|
spiSequence(&sdcard.dev, &segments[0]);
|
||||||
|
@ -245,7 +245,11 @@ static uint8_t sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
|
||||||
// Block pending completion of SPI access
|
// Block pending completion of SPI access
|
||||||
spiWait(&sdcard.dev);
|
spiWait(&sdcard.dev);
|
||||||
|
|
||||||
return idleByte;
|
if ((idleByte != SDCARD_IDLE_TOKEN) && commandCode != SDCARD_COMMAND_GO_IDLE_STATE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmdResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t sdcard_sendAppCommand(uint8_t commandCode, uint32_t commandArgument)
|
static uint8_t sdcard_sendAppCommand(uint8_t commandCode, uint32_t commandArgument)
|
||||||
|
@ -336,6 +340,30 @@ typedef enum {
|
||||||
SDCARD_RECEIVE_ERROR
|
SDCARD_RECEIVE_ERROR
|
||||||
} sdcardReceiveBlockStatus_e;
|
} sdcardReceiveBlockStatus_e;
|
||||||
|
|
||||||
|
// Called in ISR context
|
||||||
|
// Wait until the arrival of the SDCARD_SINGLE_BLOCK_READ_START_TOKEN token
|
||||||
|
busStatus_e sdcard_callbackNotIdleDataBlock(uint32_t arg)
|
||||||
|
{
|
||||||
|
sdcard_t *sdcard = (sdcard_t *)arg;
|
||||||
|
extDevice_t *dev = &sdcard->dev;
|
||||||
|
|
||||||
|
uint8_t idleByte = dev->bus->curSegment->u.buffers.rxData[0];
|
||||||
|
|
||||||
|
if (idleByte == SDCARD_SINGLE_BLOCK_READ_START_TOKEN) {
|
||||||
|
return BUS_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idleByte != SDCARD_IDLE_TOKEN) {
|
||||||
|
return BUS_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdcard->idleCount-- <= 0) {
|
||||||
|
return BUS_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BUS_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to receive a data block from the SD card.
|
* Attempt to receive a data block from the SD card.
|
||||||
*
|
*
|
||||||
|
@ -343,18 +371,13 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int count)
|
static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int count)
|
||||||
{
|
{
|
||||||
uint8_t dataToken = sdcard_waitForNonIdleByte(8);
|
uint8_t dataToken;
|
||||||
|
|
||||||
if (dataToken == 0xFF) {
|
sdcard.idleCount = SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY;
|
||||||
return SDCARD_RECEIVE_BLOCK_IN_PROGRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataToken != SDCARD_SINGLE_BLOCK_READ_START_TOKEN) {
|
|
||||||
return SDCARD_RECEIVE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that this does not release the CS at the end of the transaction
|
// Note that this does not release the CS at the end of the transaction
|
||||||
busSegment_t segments[] = {
|
busSegment_t segments[] = {
|
||||||
|
{.u.buffers = {NULL, &dataToken}, sizeof(dataToken), false, sdcard_callbackNotIdleDataBlock},
|
||||||
{.u.buffers = {NULL, buffer}, count, false, NULL},
|
{.u.buffers = {NULL, buffer}, count, false, NULL},
|
||||||
// Discard trailing CRC, we don't care
|
// Discard trailing CRC, we don't care
|
||||||
{.u.buffers = {NULL, NULL}, 2, false, NULL},
|
{.u.buffers = {NULL, NULL}, 2, false, NULL},
|
||||||
|
@ -367,7 +390,14 @@ static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int c
|
||||||
// Block pending completion of SPI access
|
// Block pending completion of SPI access
|
||||||
spiWait(&sdcard.dev);
|
spiWait(&sdcard.dev);
|
||||||
|
|
||||||
return SDCARD_RECEIVE_SUCCESS;
|
switch (dataToken) {
|
||||||
|
case SDCARD_IDLE_TOKEN:
|
||||||
|
return SDCARD_RECEIVE_BLOCK_IN_PROGRESS;
|
||||||
|
case SDCARD_SINGLE_BLOCK_READ_START_TOKEN:
|
||||||
|
return SDCARD_RECEIVE_SUCCESS;
|
||||||
|
default:
|
||||||
|
return SDCARD_RECEIVE_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sdcard_sendDataBlockFinish(void)
|
static bool sdcard_sendDataBlockFinish(void)
|
||||||
|
@ -532,7 +562,7 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s
|
||||||
if (config->chipSelectTag) {
|
if (config->chipSelectTag) {
|
||||||
chipSelectIO = IOGetByTag(config->chipSelectTag);
|
chipSelectIO = IOGetByTag(config->chipSelectTag);
|
||||||
IOInit(chipSelectIO, OWNER_SDCARD_CS, 0);
|
IOInit(chipSelectIO, OWNER_SDCARD_CS, 0);
|
||||||
IOConfigGPIO(chipSelectIO, SPI_IO_CS_CFG);
|
IOConfigGPIO(chipSelectIO, SPI_IO_CS_HIGH_CFG);
|
||||||
} else {
|
} else {
|
||||||
chipSelectIO = IO_NONE;
|
chipSelectIO = IO_NONE;
|
||||||
}
|
}
|
||||||
|
@ -554,10 +584,10 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s
|
||||||
// Transmit at least 74 dummy clock cycles with CS high so the SD card can start up
|
// Transmit at least 74 dummy clock cycles with CS high so the SD card can start up
|
||||||
IOHi(sdcard.dev.busType_u.spi.csnPin);
|
IOHi(sdcard.dev.busType_u.spi.csnPin);
|
||||||
|
|
||||||
// Note that this does not release the CS at the end of the transaction
|
// Note that CS is not asserted for this transaction
|
||||||
busSegment_t segments[] = {
|
busSegment_t segments[] = {
|
||||||
// Write a single 0xff
|
// Write a single 0xff
|
||||||
{.u.buffers = {NULL, NULL}, SDCARD_INIT_NUM_DUMMY_BYTES, false, NULL},
|
{.u.buffers = {NULL, NULL}, SDCARD_INIT_NUM_DUMMY_BYTES, true, NULL},
|
||||||
{.u.link = {NULL, NULL}, 0, true, NULL},
|
{.u.link = {NULL, NULL}, 0, true, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -566,6 +596,11 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s
|
||||||
// Block pending completion of SPI access
|
// Block pending completion of SPI access
|
||||||
spiWait(&sdcard.dev);
|
spiWait(&sdcard.dev);
|
||||||
|
|
||||||
|
// Enable the CS line
|
||||||
|
if (chipSelectIO != IO_NONE) {
|
||||||
|
IOConfigGPIO(chipSelectIO, SPI_IO_CS_CFG);
|
||||||
|
}
|
||||||
|
|
||||||
sdcard.operationStartTime = millis();
|
sdcard.operationStartTime = millis();
|
||||||
sdcard.state = SDCARD_STATE_RESET;
|
sdcard.state = SDCARD_STATE_RESET;
|
||||||
sdcard.failureCount = 0;
|
sdcard.failureCount = 0;
|
||||||
|
@ -617,8 +652,8 @@ static sdcardOperationStatus_e sdcard_endWriteBlocks(void)
|
||||||
// Block pending completion of SPI access
|
// Block pending completion of SPI access
|
||||||
spiWait(&sdcard.dev);
|
spiWait(&sdcard.dev);
|
||||||
|
|
||||||
// Card may choose to raise a busy (non-0xFF) signal after at most N_BR (1 byte) delay
|
// Card may choose to raise a busy (non-SDCARD_IDLE_TOKEN) signal after at most N_BR (1 byte) delay
|
||||||
if (sdcard_waitForNonIdleByte(1) == 0xFF) {
|
if (sdcard_waitForNonIdleByte(1) == SDCARD_IDLE_TOKEN) {
|
||||||
sdcard.state = SDCARD_STATE_READY;
|
sdcard.state = SDCARD_STATE_READY;
|
||||||
return SDCARD_OPERATION_SUCCESS;
|
return SDCARD_OPERATION_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -196,6 +196,7 @@ typedef struct sdcardCSD_t {
|
||||||
#define SDCARD_CSD_V2_TRAILER_OFFSET 127
|
#define SDCARD_CSD_V2_TRAILER_OFFSET 127
|
||||||
#define SDCARD_CSD_V2_TRAILER_LEN 1
|
#define SDCARD_CSD_V2_TRAILER_LEN 1
|
||||||
|
|
||||||
|
#define SDCARD_IDLE_TOKEN 0xFF
|
||||||
#define SDCARD_SINGLE_BLOCK_READ_START_TOKEN 0xFE
|
#define SDCARD_SINGLE_BLOCK_READ_START_TOKEN 0xFE
|
||||||
#define SDCARD_SINGLE_BLOCK_WRITE_START_TOKEN 0xFE
|
#define SDCARD_SINGLE_BLOCK_WRITE_START_TOKEN 0xFE
|
||||||
#define SDCARD_MULTIPLE_BLOCK_WRITE_START_TOKEN 0xFC
|
#define SDCARD_MULTIPLE_BLOCK_WRITE_START_TOKEN 0xFC
|
||||||
|
@ -204,13 +205,13 @@ typedef struct sdcardCSD_t {
|
||||||
#define SDCARD_BLOCK_SIZE 512
|
#define SDCARD_BLOCK_SIZE 512
|
||||||
|
|
||||||
// Idle bit is set to 1 only when idle during initialization phase:
|
// Idle bit is set to 1 only when idle during initialization phase:
|
||||||
#define SDCARD_R1_STATUS_BIT_IDLE 1
|
#define SDCARD_R1_STATUS_BIT_IDLE 0x01
|
||||||
#define SDCARD_R1_STATUS_BIT_ERASE_RESET 2
|
#define SDCARD_R1_STATUS_BIT_ERASE_RESET 0x02
|
||||||
#define SDCARD_R1_STATUS_BIT_ILLEGAL_COMMAND 4
|
#define SDCARD_R1_STATUS_BIT_ILLEGAL_COMMAND 0x04
|
||||||
#define SDCARD_R1_STATUS_BIT_COM_CRC_ERROR 8
|
#define SDCARD_R1_STATUS_BIT_COM_CRC_ERROR 0x08
|
||||||
#define SDCARD_R1_STATUS_BIT_ERASE_SEQUENCE_ERROR 16
|
#define SDCARD_R1_STATUS_BIT_ERASE_SEQUENCE_ERROR 0x10
|
||||||
#define SDCARD_R1_STATUS_BIT_ADDRESS_ERROR 32
|
#define SDCARD_R1_STATUS_BIT_ADDRESS_ERROR 0x20
|
||||||
#define SDCARD_R1_STATUS_BIT_PARAMETER_ERROR 64
|
#define SDCARD_R1_STATUS_BIT_PARAMETER_ERROR 0x40
|
||||||
|
|
||||||
#define SDCARD_CSD_STRUCTURE_VERSION_1 0
|
#define SDCARD_CSD_STRUCTURE_VERSION_1 0
|
||||||
#define SDCARD_CSD_STRUCTURE_VERSION_2 1
|
#define SDCARD_CSD_STRUCTURE_VERSION_2 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue