mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-13 03:20:00 +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 *dmaRx = dev->bus->dmaRx;
|
||||
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) {
|
||||
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);
|
||||
|
||||
// Enable streams
|
||||
xDMA_Cmd(streamRegsTx, 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.
|
||||
*/
|
||||
spi_i2s_dma_receiver_enable(dev->bus->busType_u.spi.instance, TRUE);
|
||||
|
|
|
@ -31,20 +31,23 @@
|
|||
#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_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_HIGH_CFG IO_CONFIG(GPIO_Mode_IN, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP)
|
||||
#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_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_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_HIGH_CFG IO_CONFIG(GPIO_MODE_INPUT, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
|
||||
#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_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_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_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_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_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
|
||||
|
||||
// De facto standard mode
|
||||
|
|
|
@ -91,7 +91,7 @@ typedef struct sdcard_t {
|
|||
|
||||
#ifdef USE_SDCARD_SPI
|
||||
extDevice_t dev;
|
||||
uint8_t idleCount;
|
||||
int8_t idleCount;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDCARD_SDIO
|
||||
|
|
|
@ -112,7 +112,7 @@ static void sdcard_reset(void)
|
|||
|
||||
|
||||
// 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)
|
||||
{
|
||||
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];
|
||||
|
||||
if (idleByte == 0xff) {
|
||||
return BUS_READY;
|
||||
if (idleByte == SDCARD_IDLE_TOKEN) {
|
||||
// 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;
|
||||
return BUS_ABORT;
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ busStatus_e sdcard_callbackIdle(uint32_t arg)
|
|||
|
||||
|
||||
// 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)
|
||||
{
|
||||
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];
|
||||
|
||||
if (idleByte != 0xff) {
|
||||
if (idleByte != SDCARD_IDLE_TOKEN) {
|
||||
return BUS_READY;
|
||||
}
|
||||
|
||||
if (sdcard->idleCount-- == 0) {
|
||||
if (sdcard->idleCount-- <= 0) {
|
||||
return BUS_ABORT;
|
||||
}
|
||||
|
||||
|
@ -177,11 +178,11 @@ static bool sdcard_waitForIdle(int maxBytesToWait)
|
|||
// Block pending completion of SPI access
|
||||
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.
|
||||
*/
|
||||
|
@ -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
|
||||
* 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] = {
|
||||
0x40 | commandCode,
|
||||
|
@ -226,18 +227,17 @@ static uint8_t sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
|
|||
};
|
||||
|
||||
uint8_t idleByte;
|
||||
uint8_t cmdResponse;
|
||||
|
||||
// Note that this does not release the CS at the end of the transaction
|
||||
busSegment_t segments[] = {
|
||||
{.u.buffers = {NULL, &idleByte}, sizeof(idleByte), false, sdcard_callbackIdle},
|
||||
{.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},
|
||||
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
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)
|
||||
|
@ -336,6 +340,30 @@ typedef enum {
|
|||
SDCARD_RECEIVE_ERROR
|
||||
} 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.
|
||||
*
|
||||
|
@ -343,18 +371,13 @@ typedef enum {
|
|||
*/
|
||||
static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int count)
|
||||
{
|
||||
uint8_t dataToken = sdcard_waitForNonIdleByte(8);
|
||||
uint8_t dataToken;
|
||||
|
||||
if (dataToken == 0xFF) {
|
||||
return SDCARD_RECEIVE_BLOCK_IN_PROGRESS;
|
||||
}
|
||||
|
||||
if (dataToken != SDCARD_SINGLE_BLOCK_READ_START_TOKEN) {
|
||||
return SDCARD_RECEIVE_ERROR;
|
||||
}
|
||||
sdcard.idleCount = SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY;
|
||||
|
||||
// Note that this does not release the CS at the end of the transaction
|
||||
busSegment_t segments[] = {
|
||||
{.u.buffers = {NULL, &dataToken}, sizeof(dataToken), false, sdcard_callbackNotIdleDataBlock},
|
||||
{.u.buffers = {NULL, buffer}, count, false, NULL},
|
||||
// Discard trailing CRC, we don't care
|
||||
{.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
|
||||
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)
|
||||
|
@ -532,7 +562,7 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s
|
|||
if (config->chipSelectTag) {
|
||||
chipSelectIO = IOGetByTag(config->chipSelectTag);
|
||||
IOInit(chipSelectIO, OWNER_SDCARD_CS, 0);
|
||||
IOConfigGPIO(chipSelectIO, SPI_IO_CS_CFG);
|
||||
IOConfigGPIO(chipSelectIO, SPI_IO_CS_HIGH_CFG);
|
||||
} else {
|
||||
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
|
||||
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[] = {
|
||||
// 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},
|
||||
};
|
||||
|
||||
|
@ -566,6 +596,11 @@ static void sdcardSpi_init(const sdcardConfig_t *config, const spiPinConfig_t *s
|
|||
// Block pending completion of SPI access
|
||||
spiWait(&sdcard.dev);
|
||||
|
||||
// Enable the CS line
|
||||
if (chipSelectIO != IO_NONE) {
|
||||
IOConfigGPIO(chipSelectIO, SPI_IO_CS_CFG);
|
||||
}
|
||||
|
||||
sdcard.operationStartTime = millis();
|
||||
sdcard.state = SDCARD_STATE_RESET;
|
||||
sdcard.failureCount = 0;
|
||||
|
@ -617,8 +652,8 @@ static sdcardOperationStatus_e sdcard_endWriteBlocks(void)
|
|||
// Block pending completion of SPI access
|
||||
spiWait(&sdcard.dev);
|
||||
|
||||
// Card may choose to raise a busy (non-0xFF) signal after at most N_BR (1 byte) delay
|
||||
if (sdcard_waitForNonIdleByte(1) == 0xFF) {
|
||||
// Card may choose to raise a busy (non-SDCARD_IDLE_TOKEN) signal after at most N_BR (1 byte) delay
|
||||
if (sdcard_waitForNonIdleByte(1) == SDCARD_IDLE_TOKEN) {
|
||||
sdcard.state = SDCARD_STATE_READY;
|
||||
return SDCARD_OPERATION_SUCCESS;
|
||||
} else {
|
||||
|
|
|
@ -196,6 +196,7 @@ typedef struct sdcardCSD_t {
|
|||
#define SDCARD_CSD_V2_TRAILER_OFFSET 127
|
||||
#define SDCARD_CSD_V2_TRAILER_LEN 1
|
||||
|
||||
#define SDCARD_IDLE_TOKEN 0xFF
|
||||
#define SDCARD_SINGLE_BLOCK_READ_START_TOKEN 0xFE
|
||||
#define SDCARD_SINGLE_BLOCK_WRITE_START_TOKEN 0xFE
|
||||
#define SDCARD_MULTIPLE_BLOCK_WRITE_START_TOKEN 0xFC
|
||||
|
@ -204,13 +205,13 @@ typedef struct sdcardCSD_t {
|
|||
#define SDCARD_BLOCK_SIZE 512
|
||||
|
||||
// Idle bit is set to 1 only when idle during initialization phase:
|
||||
#define SDCARD_R1_STATUS_BIT_IDLE 1
|
||||
#define SDCARD_R1_STATUS_BIT_ERASE_RESET 2
|
||||
#define SDCARD_R1_STATUS_BIT_ILLEGAL_COMMAND 4
|
||||
#define SDCARD_R1_STATUS_BIT_COM_CRC_ERROR 8
|
||||
#define SDCARD_R1_STATUS_BIT_ERASE_SEQUENCE_ERROR 16
|
||||
#define SDCARD_R1_STATUS_BIT_ADDRESS_ERROR 32
|
||||
#define SDCARD_R1_STATUS_BIT_PARAMETER_ERROR 64
|
||||
#define SDCARD_R1_STATUS_BIT_IDLE 0x01
|
||||
#define SDCARD_R1_STATUS_BIT_ERASE_RESET 0x02
|
||||
#define SDCARD_R1_STATUS_BIT_ILLEGAL_COMMAND 0x04
|
||||
#define SDCARD_R1_STATUS_BIT_COM_CRC_ERROR 0x08
|
||||
#define SDCARD_R1_STATUS_BIT_ERASE_SEQUENCE_ERROR 0x10
|
||||
#define SDCARD_R1_STATUS_BIT_ADDRESS_ERROR 0x20
|
||||
#define SDCARD_R1_STATUS_BIT_PARAMETER_ERROR 0x40
|
||||
|
||||
#define SDCARD_CSD_STRUCTURE_VERSION_1 0
|
||||
#define SDCARD_CSD_STRUCTURE_VERSION_2 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue