1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-16 12:55:19 +03:00

Refactor sdcard_spi.c to use busDevice_t (again)

This commit is contained in:
jflyper 2018-10-04 12:01:52 +09:00
parent a598d06fe5
commit 6307277d50
4 changed files with 62 additions and 51 deletions

View file

@ -141,6 +141,11 @@ void spiResetErrorCounter(SPI_TypeDef *instance)
} }
} }
bool spiBusIsBusBusy(const busDevice_t *bus)
{
return spiIsBusBusy(bus->busdev_u.spi.instance);
}
uint8_t spiBusTransferByte(const busDevice_t *bus, uint8_t data) uint8_t spiBusTransferByte(const busDevice_t *bus, uint8_t data)
{ {
return spiTransferByte(bus->busdev_u.spi.instance, data); return spiTransferByte(bus->busdev_u.spi.instance, data);
@ -153,6 +158,11 @@ void spiBusWriteByte(const busDevice_t *bus, uint8_t data)
IOHi(bus->busdev_u.spi.csnPin); IOHi(bus->busdev_u.spi.csnPin);
} }
bool spiBusRawTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int len)
{
return spiTransfer(bus->busdev_u.spi.instance, txData, rxData, len);
}
bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data) bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data)
{ {
IOLo(bus->busdev_u.spi.csnPin); IOLo(bus->busdev_u.spi.csnPin);

View file

@ -112,10 +112,13 @@ void spiResetErrorCounter(SPI_TypeDef *instance);
SPIDevice spiDeviceByInstance(SPI_TypeDef *instance); SPIDevice spiDeviceByInstance(SPI_TypeDef *instance);
SPI_TypeDef *spiInstanceByDevice(SPIDevice device); SPI_TypeDef *spiInstanceByDevice(SPIDevice device);
bool spiBusIsBusBusy(const busDevice_t *bus);
bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length); bool spiBusTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int length);
uint8_t spiBusTransferByte(const busDevice_t *bus, uint8_t data); uint8_t spiBusTransferByte(const busDevice_t *bus, uint8_t data);
void spiBusWriteByte(const busDevice_t *bus, uint8_t data); void spiBusWriteByte(const busDevice_t *bus, uint8_t data);
bool spiBusRawTransfer(const busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int len);
bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data); bool spiBusWriteRegister(const busDevice_t *bus, uint8_t reg, uint8_t data);
bool spiBusRawReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length); bool spiBusRawReadRegisterBuffer(const busDevice_t *bus, uint8_t reg, uint8_t *data, uint8_t length);

View file

@ -90,8 +90,7 @@ typedef struct sdcard_t {
IO_t cardDetectPin; IO_t cardDetectPin;
#ifdef USE_SDCARD_SPI #ifdef USE_SDCARD_SPI
SPI_TypeDef *instance; busDevice_t busdev;
IO_t chipSelectPin;
bool useDMAForTx; bool useDMAForTx;
dmaChannelDescriptor_t * dma; dmaChannelDescriptor_t * dma;
#endif #endif

View file

@ -40,9 +40,6 @@
#define SDCARD_PROFILING #define SDCARD_PROFILING
#endif #endif
#define SET_CS_HIGH IOHi(sdcard.chipSelectPin)
#define SET_CS_LOW IOLo(sdcard.chipSelectPin)
#define SDCARD_INIT_NUM_DUMMY_BYTES 10 #define SDCARD_INIT_NUM_DUMMY_BYTES 10
#define SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY 8 #define SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY 8
// Chosen so that CMD8 will have the same CRC as CMD0: // Chosen so that CMD8 will have the same CRC as CMD0:
@ -70,18 +67,18 @@ static bool sdcardSpi_isFunctional(void)
static void sdcard_select(void) static void sdcard_select(void)
{ {
SET_CS_LOW; IOLo(sdcard.busdev.busdev_u.spi.csnPin);
} }
static void sdcard_deselect(void) static void sdcard_deselect(void)
{ {
// As per the SD-card spec, give the card 8 dummy clocks so it can finish its operation // As per the SD-card spec, give the card 8 dummy clocks so it can finish its operation
//spiTransferByte(sdcard.instance, 0xFF); //spiBusTransferByte(&sdcard.busdev, 0xFF);
while (spiIsBusBusy(sdcard.instance)) { while (spiBusIsBusBusy(&sdcard.busdev)) {
} }
SET_CS_HIGH; IOHi(sdcard.busdev.busdev_u.spi.csnPin);
} }
/** /**
@ -98,7 +95,7 @@ static void sdcard_reset(void)
} }
if (sdcard.state >= SDCARD_STATE_READY) { if (sdcard.state >= SDCARD_STATE_READY) {
spiSetDivisor(sdcard.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER);
} }
sdcard.failureCount++; sdcard.failureCount++;
@ -118,7 +115,7 @@ static void sdcard_reset(void)
static bool sdcard_waitForIdle(int maxBytesToWait) static bool sdcard_waitForIdle(int maxBytesToWait)
{ {
while (maxBytesToWait > 0) { while (maxBytesToWait > 0) {
uint8_t b = spiTransferByte(sdcard.instance, 0xFF); uint8_t b = spiBusTransferByte(&sdcard.busdev, 0xFF);
if (b == 0xFF) { if (b == 0xFF) {
return true; return true;
} }
@ -136,7 +133,7 @@ static bool sdcard_waitForIdle(int maxBytesToWait)
static uint8_t sdcard_waitForNonIdleByte(int maxDelay) static uint8_t sdcard_waitForNonIdleByte(int maxDelay)
{ {
for (int i = 0; i < maxDelay + 1; i++) { // + 1 so we can wait for maxDelay '0xFF' bytes before reading a response byte afterwards for (int i = 0; i < maxDelay + 1; i++) { // + 1 so we can wait for maxDelay '0xFF' bytes before reading a response byte afterwards
uint8_t response = spiTransferByte(sdcard.instance, 0xFF); uint8_t response = spiBusTransferByte(&sdcard.busdev, 0xFF);
if (response != 0xFF) { if (response != 0xFF) {
return response; return response;
@ -171,7 +168,7 @@ static uint8_t sdcard_sendCommand(uint8_t commandCode, uint32_t commandArgument)
if (!sdcard_waitForIdle(SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY) && commandCode != SDCARD_COMMAND_GO_IDLE_STATE) if (!sdcard_waitForIdle(SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY) && commandCode != SDCARD_COMMAND_GO_IDLE_STATE)
return 0xFF; return 0xFF;
spiTransfer(sdcard.instance, command, NULL, sizeof(command)); spiBusRawTransfer(&sdcard.busdev, command, NULL, sizeof(command));
/* /*
* The card can take up to SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY bytes to send the response, in the meantime * The card can take up to SDCARD_MAXIMUM_BYTE_DELAY_FOR_CMD_REPLY bytes to send the response, in the meantime
@ -207,7 +204,7 @@ static bool sdcard_validateInterfaceCondition(void)
// V1 cards don't support this command // V1 cards don't support this command
sdcard.version = 1; sdcard.version = 1;
} else if (status == SDCARD_R1_STATUS_BIT_IDLE) { } else if (status == SDCARD_R1_STATUS_BIT_IDLE) {
spiTransfer(sdcard.instance, NULL, ifCondReply, sizeof(ifCondReply)); spiBusRawTransfer(&sdcard.busdev, NULL, ifCondReply, sizeof(ifCondReply));
/* /*
* We don't bother to validate the SDCard's operating voltage range since the spec requires it to accept our * We don't bother to validate the SDCard's operating voltage range since the spec requires it to accept our
@ -231,7 +228,7 @@ static bool sdcard_readOCRRegister(uint32_t *result)
uint8_t response[4]; uint8_t response[4];
spiTransfer(sdcard.instance, NULL, response, sizeof(response)); spiBusRawTransfer(&sdcard.busdev, NULL, response, sizeof(response));
if (status == 0) { if (status == 0) {
sdcard_deselect(); sdcard_deselect();
@ -269,11 +266,11 @@ static sdcardReceiveBlockStatus_e sdcard_receiveDataBlock(uint8_t *buffer, int c
return SDCARD_RECEIVE_ERROR; return SDCARD_RECEIVE_ERROR;
} }
spiTransfer(sdcard.instance, NULL, buffer, count); spiBusRawTransfer(&sdcard.busdev, NULL, buffer, count);
// Discard trailing CRC, we don't care // Discard trailing CRC, we don't care
spiTransferByte(sdcard.instance, 0xFF); spiBusTransferByte(&sdcard.busdev, 0xFF);
spiTransferByte(sdcard.instance, 0xFF); spiBusTransferByte(&sdcard.busdev, 0xFF);
return SDCARD_RECEIVE_SUCCESS; return SDCARD_RECEIVE_SUCCESS;
} }
@ -283,16 +280,16 @@ static bool sdcard_sendDataBlockFinish(void)
#ifdef USE_HAL_DRIVER #ifdef USE_HAL_DRIVER
// Drain anything left in the Rx FIFO (we didn't read it during the write) // Drain anything left in the Rx FIFO (we didn't read it during the write)
//This is necessary here as when using msc there is timing issue //This is necessary here as when using msc there is timing issue
while (LL_SPI_IsActiveFlag_RXNE(sdcard.instance)) { while (LL_SPI_IsActiveFlag_RXNE(sdcard.busdev.busdev_u.spi.instance)) {
sdcard.instance->DR; sdcard.busdev.busdev_u.spi.instance->DR;
} }
#endif #endif
// Send a dummy CRC // Send a dummy CRC
spiTransferByte(sdcard.instance, 0x00); spiBusTransferByte(&sdcard.busdev, 0x00);
spiTransferByte(sdcard.instance, 0x00); spiBusTransferByte(&sdcard.busdev, 0x00);
uint8_t dataResponseToken = spiTransferByte(sdcard.instance, 0xFF); uint8_t dataResponseToken = spiBusTransferByte(&sdcard.busdev, 0xFF);
/* /*
* Check if the card accepted the write (no CRC error / no address error) * Check if the card accepted the write (no CRC error / no address error)
@ -315,9 +312,9 @@ static bool sdcard_sendDataBlockFinish(void)
static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrite) static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrite)
{ {
// Card wants 8 dummy clock cycles between the write command's response and a data block beginning: // Card wants 8 dummy clock cycles between the write command's response and a data block beginning:
spiTransferByte(sdcard.instance, 0xFF); spiBusTransferByte(&sdcard.busdev, 0xFF);
spiTransferByte(sdcard.instance, multiBlockWrite ? SDCARD_MULTIPLE_BLOCK_WRITE_START_TOKEN : SDCARD_SINGLE_BLOCK_WRITE_START_TOKEN); spiBusTransferByte(&sdcard.busdev, multiBlockWrite ? SDCARD_MULTIPLE_BLOCK_WRITE_START_TOKEN : SDCARD_SINGLE_BLOCK_WRITE_START_TOKEN);
if (sdcard.useDMAForTx) { if (sdcard.useDMAForTx) {
#if defined(USE_HAL_DRIVER) #if defined(USE_HAL_DRIVER)
@ -329,7 +326,7 @@ static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrit
init.Mode = LL_DMA_MODE_NORMAL; init.Mode = LL_DMA_MODE_NORMAL;
init.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; init.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
init.PeriphOrM2MSrcAddress = (uint32_t)&sdcard.instance->DR; init.PeriphOrM2MSrcAddress = (uint32_t)&sdcard.busdev.busdev_u.spi.instance->DR;
init.Priority = LL_DMA_PRIORITY_LOW; init.Priority = LL_DMA_PRIORITY_LOW;
init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
@ -345,7 +342,7 @@ static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrit
LL_DMA_EnableStream(sdcard.dma->dma, sdcard.dma->stream); LL_DMA_EnableStream(sdcard.dma->dma, sdcard.dma->stream);
LL_SPI_EnableDMAReq_TX(sdcard.instance); LL_SPI_EnableDMAReq_TX(sdcard.busdev.busdev_u.spi.instance);
#else #else
@ -361,7 +358,7 @@ static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrit
init.DMA_MemoryBaseAddr = (uint32_t) buffer; init.DMA_MemoryBaseAddr = (uint32_t) buffer;
init.DMA_DIR = DMA_DIR_PeripheralDST; init.DMA_DIR = DMA_DIR_PeripheralDST;
#endif #endif
init.DMA_PeripheralBaseAddr = (uint32_t) &sdcard.instance->DR; init.DMA_PeripheralBaseAddr = (uint32_t) &sdcard.busdev.busdev_u.spi.instance->DR;
init.DMA_Priority = DMA_Priority_Low; init.DMA_Priority = DMA_Priority_Low;
init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
@ -377,11 +374,11 @@ static void sdcard_sendDataBlockBegin(const uint8_t *buffer, bool multiBlockWrit
DMA_Cmd(sdcard.dma->ref, ENABLE); DMA_Cmd(sdcard.dma->ref, ENABLE);
SPI_I2S_DMACmd(sdcard.instance, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(sdcard.busdev.busdev_u.spi.instance, SPI_I2S_DMAReq_Tx, ENABLE);
#endif #endif
} else { } else {
// Send the first chunk now // Send the first chunk now
spiTransfer(sdcard.instance, buffer, NULL, SDCARD_NON_DMA_CHUNK_SIZE); spiBusRawTransfer(&sdcard.busdev, buffer, NULL, SDCARD_NON_DMA_CHUNK_SIZE);
} }
} }
@ -479,7 +476,7 @@ static void sdcardSpi_init(const sdcardConfig_t *config)
return; return;
} }
sdcard.instance = spiInstanceByDevice(SPI_CFG_TO_DEV(config->device)); spiBusSetInstance(&sdcard.busdev, spiInstanceByDevice(SPI_CFG_TO_DEV(config->device)));
sdcard.useDMAForTx = config->useDma; sdcard.useDMAForTx = config->useDma;
if (sdcard.useDMAForTx) { if (sdcard.useDMAForTx) {
@ -490,13 +487,15 @@ static void sdcardSpi_init(const sdcardConfig_t *config)
dmaInit(config->dmaIdentifier, OWNER_SDCARD, 0); dmaInit(config->dmaIdentifier, OWNER_SDCARD, 0);
} }
IO_t chipSelectIO;
if (config->chipSelectTag) { if (config->chipSelectTag) {
sdcard.chipSelectPin = IOGetByTag(config->chipSelectTag); chipSelectIO = IOGetByTag(config->chipSelectTag);
IOInit(sdcard.chipSelectPin, OWNER_SDCARD_CS, 0); IOInit(chipSelectIO, OWNER_SDCARD_CS, 0);
IOConfigGPIO(sdcard.chipSelectPin, SPI_IO_CS_CFG); IOConfigGPIO(chipSelectIO, SPI_IO_CS_CFG);
} else { } else {
sdcard.chipSelectPin = IO_NONE; chipSelectIO = IO_NONE;
} }
sdcard.busdev.busdev_u.spi.csnPin = chipSelectIO;
if (config->cardDetectTag) { if (config->cardDetectTag) {
sdcard.cardDetectPin = IOGetByTag(config->cardDetectTag); sdcard.cardDetectPin = IOGetByTag(config->cardDetectTag);
@ -507,19 +506,19 @@ static void sdcardSpi_init(const sdcardConfig_t *config)
} }
// Max frequency is initially 400kHz // Max frequency is initially 400kHz
spiSetDivisor(sdcard.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER); spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER);
// SDCard wants 1ms minimum delay after power is applied to it // SDCard wants 1ms minimum delay after power is applied to it
delay(1000); delay(1000);
// 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
SET_CS_HIGH; IOHi(sdcard.busdev.busdev_u.spi.csnPin);
spiTransfer(sdcard.instance, NULL, NULL, SDCARD_INIT_NUM_DUMMY_BYTES); spiBusRawTransfer(&sdcard.busdev, NULL, NULL, SDCARD_INIT_NUM_DUMMY_BYTES);
// Wait for that transmission to finish before we enable the SDCard, so it receives the required number of cycles: // Wait for that transmission to finish before we enable the SDCard, so it receives the required number of cycles:
int time = 100000; int time = 100000;
while (spiIsBusBusy(sdcard.instance)) { while (spiBusIsBusBusy(&sdcard.busdev)) {
if (time-- == 0) { if (time-- == 0) {
sdcard.state = SDCARD_STATE_NOT_PRESENT; sdcard.state = SDCARD_STATE_NOT_PRESENT;
sdcard.failureCount++; sdcard.failureCount++;
@ -566,9 +565,9 @@ static sdcardOperationStatus_e sdcard_endWriteBlocks(void)
sdcard.multiWriteBlocksRemain = 0; sdcard.multiWriteBlocksRemain = 0;
// 8 dummy clocks to guarantee N_WR clocks between the last card response and this token // 8 dummy clocks to guarantee N_WR clocks between the last card response and this token
spiTransferByte(sdcard.instance, 0xFF); spiBusTransferByte(&sdcard.busdev, 0xFF);
spiTransferByte(sdcard.instance, SDCARD_MULTIPLE_BLOCK_WRITE_STOP_TOKEN); spiBusTransferByte(&sdcard.busdev, SDCARD_MULTIPLE_BLOCK_WRITE_STOP_TOKEN);
// 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-0xFF) signal after at most N_BR (1 byte) delay
if (sdcard_waitForNonIdleByte(1) == 0xFF) { if (sdcard_waitForNonIdleByte(1) == 0xFF) {
@ -672,7 +671,7 @@ static bool sdcardSpi_poll(void)
} }
// Now we're done with init and we can switch to the full speed clock (<25MHz) // Now we're done with init and we can switch to the full speed clock (<25MHz)
spiSetDivisor(sdcard.instance, SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER); spiSetDivisor(sdcard.busdev.busdev_u.spi.instance, SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER);
sdcard.multiWriteBlocksRemain = 0; sdcard.multiWriteBlocksRemain = 0;
@ -690,15 +689,15 @@ static bool sdcardSpi_poll(void)
DMA_CLEAR_FLAG(sdcard.dma, DMA_IT_TCIF); DMA_CLEAR_FLAG(sdcard.dma, DMA_IT_TCIF);
DMA_CLEAR_FLAG(sdcard.dma, DMA_IT_HTIF); DMA_CLEAR_FLAG(sdcard.dma, DMA_IT_HTIF);
// Drain anything left in the Rx FIFO (we didn't read it during the write) // Drain anything left in the Rx FIFO (we didn't read it during the write)
while (LL_SPI_IsActiveFlag_RXNE(sdcard.instance)) { while (LL_SPI_IsActiveFlag_RXNE(sdcard.busdev.busdev_u.spi.instance)) {
sdcard.instance->DR; sdcard.busdev.busdev_u.spi.instance->DR;
} }
// Wait for the final bit to be transmitted // Wait for the final bit to be transmitted
while (spiIsBusBusy(sdcard.instance)) { while (spiBusIsBusBusy(&sdcard.busdev)) {
} }
LL_SPI_DisableDMAReq_TX(sdcard.instance); LL_SPI_DisableDMAReq_TX(sdcard.busdev.busdev_u.spi.instance);
sendComplete = true; sendComplete = true;
} }
@ -714,22 +713,22 @@ static bool sdcardSpi_poll(void)
DMA_Cmd(sdcard.dma->ref, DISABLE); DMA_Cmd(sdcard.dma->ref, DISABLE);
// Drain anything left in the Rx FIFO (we didn't read it during the write) // Drain anything left in the Rx FIFO (we didn't read it during the write)
while (SPI_I2S_GetFlagStatus(sdcard.instance, SPI_I2S_FLAG_RXNE) == SET) { while (SPI_I2S_GetFlagStatus(sdcard.busdev.busdev_u.spi.instance, SPI_I2S_FLAG_RXNE) == SET) {
sdcard.instance->DR; sdcard.busdev.busdev_u.spi.instance->DR;
} }
// Wait for the final bit to be transmitted // Wait for the final bit to be transmitted
while (spiIsBusBusy(sdcard.instance)) { while (spiBusIsBusBusy(&sdcard.busdev)) {
} }
SPI_I2S_DMACmd(sdcard.instance, SPI_I2S_DMAReq_Tx, DISABLE); SPI_I2S_DMACmd(sdcard.busdev.busdev_u.spi.instance, SPI_I2S_DMAReq_Tx, DISABLE);
sendComplete = true; sendComplete = true;
} }
#endif #endif
if (!sdcard.useDMAForTx) { if (!sdcard.useDMAForTx) {
// Send another chunk // Send another chunk
spiTransfer(sdcard.instance, sdcard.pendingOperation.buffer + SDCARD_NON_DMA_CHUNK_SIZE * sdcard.pendingOperation.chunkIndex, NULL, SDCARD_NON_DMA_CHUNK_SIZE); spiBusRawTransfer(&sdcard.busdev, sdcard.pendingOperation.buffer + SDCARD_NON_DMA_CHUNK_SIZE * sdcard.pendingOperation.chunkIndex, NULL, SDCARD_NON_DMA_CHUNK_SIZE);
sdcard.pendingOperation.chunkIndex++; sdcard.pendingOperation.chunkIndex++;